# Manage resources [Resource initialization](https://docs.upsun.com/manage-resources/resource-init.html)
When you first deploy your project or add a new container to it,
Upsun uses [default resources](#default-resources)
unless you specify a [resource initialization strategy](#specify-a-resource-initialization-strategy).
You can also use a specific resource initialization strategy when performing certain actions,
such as [branching](#environment-branch), [merging](#environment-merge),
and [activating](#environment-activation) an environment, or [restoring a backup](#backup-restoration).
## Default resources
Upsun allocates the following default resources to every container when deployed for the first time:
| Resource type | Amount |
| --------------------------- | ----------- |
| CPU | 0.5 |
| RAM | Depends on the [container profile](/manage-resources/adjust-resources.md#advanced-container-profiles). |
| Disk size (only applicable if the app or service requires a disk) | 512 MB |
If you don't want to use these default resources, you can specify a [resource initialization strategy](/manage-resources/resource-init.md#specify-a-resource-initialization-strategy).
You can also [adjust resources](/manage-resources/adjust-resources.md) after your project or new container has been deployed.
## Specify a resource initialization strategy
Upsun provides the following resource initialization strategies:
| Strategy | Description |
| ---------| ----------- |
| `default` | Initializes new containers using the [Upsun default resources](#default-resources).This strategy applies when you first deploy your project (or new container) unless you explicitly specify a different strategy, or allocate resources manually via the `resources:set` CLI command. |
| `manual` | With this strategy, the first deployment fails and you need to configure resources manually through [the Console](https://console.upsun.com/), or using `resources:set` in the CLI. This strategy allows you to set the exact resources you want, with a single deployment. Other strategies may require fine-tuning, and therefore generate a second deployment. In this case, your environment would run for a short time with unwanted resources, and both deployments would generate downtime.|
| `minimum` | Initializes new containers using the Upsun minimum resources (see below). |
| `parent` | Initializes new containers using the same resources as on the parent environment.If there is no parent environment, or if the container doesn't already exist on the parent, the `default` strategy applies instead. |
| `child` | Initializes new containers using the same resources as on the child environment. Only relevant during merge activities. |
| `backup` | When restoring a backup, initializes new containers using the same resources as when the backup was taken. |
More information on…
Upsun minimum resources
The following table shows the resources Upsun allocates to your containers when you opt for the minimumresource initialization strategy.
Container
CPU
RAM
Disk*
.NET core
0.1
64 MB
0 MB
Chrome Headless
0.1
64 MB
None
Elasticsearch
0.1
448 MB
256 MB
Elasticsearch Premium
0.1
448 MB
256 MB
Elixir
0.1
64 MB
0 MB
Go
0.1
64 MB
0 MB
InfluxDB
0.1
448 MB
256 MB
Java
0.1
448 MB
0 MB
Kafka
0.1
448 MB
512 MB
Lisp
0.1
64 MB
0 MB
MariaDB
0.1
448 MB
256 MB
Memcached
0.1
352 MB
None
MongoDB
0.1
448 MB
256 MB
MongoDB Premium
0.1
448 MB
256 MB
Network Storage
0.1
448 MB
256 MB
Node.js
0.1
64 MB
0 MB
OpenSearch
0.1
448 MB
256 MB
Oracle MySQL
0.1
448 MB
256 MB
PHP
0.1
64 MB
0 MB
PostgreSQL
0.1
448 MB
256 MB
Python
0.1
64 MB
0 MB
RabbitMQ
0.1
448 MB
256 MB
Redis ephemeral
0.1
352 MB
None
Redis persistent
0.1
352 MB
256 MB
Ruby
0.1
64 MB
0 MB
Rust
0.1
64 MB
0 MB
Solr
0.1
448 MB
256 MB
Varnish
0.1
448 MB
None
Vault KMS
0.1
448 MB
256 MB
* The disk size is set to None when the container never uses disk, and to 0 MB when the container doesn’t require disk but can use it.
You can specify a resource initialization strategy when performing the following actions:
| Action | Available strategies | Default |
|-----------------------------------------------------------------------|------------------------------------------|----------|
| [First deployment](#first-deployment) | `parent`, `default`, `minimum`, `manual` | `parent` |
| [Environment branch](#environment-branch) | `parent`, `default`, `minimum` | `parent` |
| [Environment merge](#environment-merge) | `child`, `default`, `minimum`, `manual` | `child` |
| [Environment activation](#environment-activation) | `parent`, `default`, `minimum` | `parent` |
| [Backup restoration](#backup-restoration) | `backup`, `parent`, `default`, `minimum` | `backup` |
### First deployment
You can define [which resource initialization strategy](#specify-a-resource-initialization-strategy) Upsun uses to allocate resources
when you first deploy your project or add a new container.
If you’re not using a source integration,
you can use a Git push option to specify a resource initialization strategy.
To do so, run the following command:
For example, to use the minimum strategy for your deployment, run the following command:
Terminal
upsun push --resources-init=minimum
Note
Alternatively, you can use the official Git syntax for push options:
Terminal
git push upsun -o resources.init=minimum
Note that you can specify a different resource initialization strategy for each of your deployments.
If you’re using a source integration,
you can use the --resources-init flag to specify a resource initialization strategy.
Note
Once a resource initialization strategy is specified for your source integration,
it applies to all the deployments you launch through that source integration.
By default, when you [branch an environment](/glossary.md#branch) to create a new child environment,
the child environment inherits all the resources from its parent.
However, you can specify a different [resource initialization strategy](#specify-a-resource-initialization-strategy).
Note
When you branch an environment, regardless of the strategy you specified,
Upsun checks if the child environment’s disk size is at least equivalent to the parent’s.
If not, the parent environment’s disk size is automatically applied to the child environment.
This ensures the branching can succeed.
When you [merge](/glossary.md#merge) a child environment into its parent environment,
any apps and services you created on the child are merged and therefore created on the parent.
When this happens, any new app or service container created on the parent environment is granted the same resources as on the child environment.
However, you can specify a different resource initialization strategy.
Note
Any other container already running on the parent environment keeps its resources.
When you activate an environment, Upsun uses the same resource allocation as on the parent environment.
If there is no parent environment, the [`default` resource initialization strategy](#default-resources) applies.
You can also specify a different resource initialization strategy using the CLI.
To do so, run the following command:
```bash {location="Terminal"}
upsun environment:activate --resources-init=INITIALIZATION_STRATEGY
```
For example, to use the `minimum` resource initialization strategy, run the following command:
```bash {location="Terminal"}
upsun environment:activate --resources-init=minimum
```
Note
Setting resources on a inactive environment using the Console or the CLI automatically activates it.
When you restore a backup using the CLI,
you can restore it to your current environment or a different environment.
Backup restoration to your current environment
By default, when you restore a backup using the CLI, it is restored to your current environment.
The resources of every container already running on the environment are reverted to their original state when the backup was taken.
Note
If you don’t want to restore the resources from when the backup was taken,
opt out of restoring the resources.
To do so, when you restore your backup, use the --no-resources option.
If you deleted containers after backing up but before restoring, they are recreated using the backup strategy.
Meaning, they are granted the same resources as in the backup.
Note
If you don’t want to restore previously deleted containers,
opt out of restoring the code.
To do so, when you restore your backup, use the --no-code option.
When you restore previously deleted containers,
you can specify a different resource initialization strategy for them.
Backup restoration to a different environment
The backup strategy also applies by default.
All apps and services are initialized as new containers on the environment,
and granted the same resources as in the backup.
Note that you can specify a different resource initialization strategy for all of them.
Specify a resource initialization strategy when restoring a backup via the CLI
For example, to use the minimum resource initialization strategy, run the following command:
Terminal
upsun backup:restore --resources-init=minimum
When you restore a backup using the Console, it is restored to your current environment.
The resources of every container already running on the environment are reverted to their original state when the backup was taken.
Note
If you don’t want to restore the resources from when the backup was taken,
opt out of restoring the resources.
To do so, when you restore your backup, use the --no-resources option.
If you deleted containers after backing up but before restoring, they are recreated using the backup strategy.
Meaning, they are granted the same resources as in the backup.
Note
If you don’t want to restore previously deleted containers,
opt out of restoring the code.
To do so, restore the backup using the CLI, and use the --no-code option.
## Environment sync
[Syncing an environment](/glossary.md#sync) means merging changes from a parent environment into a child environment.
You can sync:
- Only the code
- Only the data (databases, files)
- Only the resources (CPU and RAM, instances, and disk space)
- Any combination of the three (code and data, data and resources, etc.)
Note
When you sync the data, Upsun checks if the child environment’s disk size is at least equivalent to the parent’s.
If not, the parent environment’s disk size is automatically applied to the child environment.
This ensures the sync can succeed.
Run the following commands depending on your needs:
Sync only resources:
Terminal
upsun sync resources
Sync only code:
Terminal
upsun sync code
Sync only data:
Terminal
upsun sync data
Sync everything:
Terminal
upsun sync code data resources
You can adjust the command depending on the exact combination of elements you want to sync.
Navigate to your Production environment.
Click Sync.
Select the sync options you want from the proposed list.
Select Sync resources from Production into Staging.
Click Sync.
# Deploy Laravel on Upsun [Get started](https://docs.upsun.com/get-started/stacks/laravel/get-started.html)
This guide provides instructions for deploying and working with Laravel on Upsun.
## Before you begin
You need:
- [Git](https://git-scm.com/downloads).
Git is the primary tool to manage everything your app needs to run.
Push commits to deploy changes and control configuration through YAML files.
These files describe your infrastructure, making it transparent and version-controlled.
- A Upsun account.
If you don't already have one, [register for a trial account](https://auth.upsun.com/register).
You can sign up with an email address or an existing GitHub, Bitbucket, or Google account.
If you choose one of these accounts, you can set a password for your Upsun account later.
- The [Upsun CLI](/administration/cli/_index.md).
This lets you interact with your project from the command line.
You can also do most things through the [Web Console](/administration/web/_index.md).
## 1. Create your Laravel app
1. To create a new Laravel project, run the following commands:
```bash {location="Terminal"}
composer create-project laravel/laravel:^11.0 PROJECT_NAME
cd PROJECT_NAME
git init .
```
Alternatively, you can deploy an **existing Laravel project**. To do so, `cd` into your Laravel repository root folder.
2. To generate a sensible default Upsun configuration,
run the following command from within the project's directory:
```bash {location="Terminal"}
upsun project:init
```
The Upsun CLI detects a PHP & Laravel stack.
Follow the prompts to specify a name for your project and select the needed services.
While optional, it is recommended to add [Redis](/add-services/redis.md) to your project to handle Laravel cache, queues & sessions.
The `.upsun/config.yaml` and `.environment` configuration files are generated.
3. Enable the PHP extensions required by the services you selected.
For example, `pdo_mysql` is enabled by default, but you may need to enable others like `redis` or `pdo_pgsql`:
```yaml {configFile="app"}
applications:
myapp:
[...]
runtime:
extensions:
- redis
- pdo_pgsql
```
See all the [available PHP extensions](/languages/php/extensions.html).
3. Laravel requires an [encryption key](https://laravel.com/docs/master/encryption#gracefully-rotating-encryption-keys).
To generate the key locally, run `php artisan key:generate`.
Copy the key from your local `.env` file into `.environment` as follows:
```bash {configFile="env"}
export APP_KEY="base64:APP_KEY"
```
4. Add and commit your changes:
```bash {location="Terminal"}
git add .upsun/config.yaml .environment
git commit -m "Add Upsun configuration"
```
## 2. Create your Upsun project
To create a project on Upsun, run the following command from within the project's directory:
```bash {location="Terminal"}
upsun project:create --title PROJECT_TITLE --set-remote
```
The `--set-remote` flag sets the new project as the remote for this repository.
Tip
You can link any repository to an existing Upsun project using the following command:
Terminal
upsun project:set-remote PROJECT_ID
## 3. Deploy your project
To deploy your project, run the following command:
```bash {location="Terminal"}
upsun push
```
During deployment, the logs from the Upsun API are displayed in your terminal so you can monitor progress.
To stop the display of the logs **without interrupting the deployment**,
use `CTRL+C` in your terminal.
To go back to displaying the logs, run `upsun activity:log`.
Congratulations, your first Laravel app has been deployed on Upsun!
## 4. Configure write access
The Upsun default configuration stipulates three writable folders in `.upsun/config.yaml`:
- `"/.config"`
- `"bootstrap/cache"`
- `"storage"`
If your application writes content outside of these default ones,
you can [set up mounts](/create-apps/app-reference/single-runtime-image#mounts).
## 5. Make changes to your project
Now that your project is deployed, you can start making changes to it.
For example, you might want to fix a bug or add a new feature.
In your project, the main branch always represents the production environment.
Other branches are for developing new features, fixing bugs, or updating the infrastructure.
To make changes to your project, follow these steps:
1. Create a new environment (a Git branch) to make changes without impacting production:
```bash {location="Terminal"}
upsun branch feat-a
```
This command creates a new local `feat-a` Git branch based on the main Git branch,
and activates a related environment on Upsun.
The new environment inherits the data (service data and assets) of its parent environment (the production environment here).
2. Make changes to your project.
For example, edit the `resources/views/welcome.blade.php` template and make the following visual changes:
```html {location="resources/views/welcome.blade.php"}
- Laravel
+ Laravel On Upsun
```
3. Add and commit your changes:
```bash {location="Terminal"}
add .
git commit -a -m "Update title"
```
4. Deploy your changes to the `feat-a` environment:
```bash {location="Terminal"}
upsun deploy
```
Note that each environment has its own domain name.
To view the domain name of your new environment, run the following command:
```bash {location="Terminal"}
upsun url --primary
```
5. Iterate by changing the code, committing, and deploying.
When satisfied with your changes, merge them to the main branch, deploy,
and remove the feature branch:
```bash {location="Terminal"}
git checkout main
git merge feat-a
upsun environment:delete feat-a
git branch -d feat-a
upsun deploy
```
Note that deploying to production is fast because the image built for the `feat-a` environment is reused.
For a long running branch, keep the code up-to-date with the main branch by using `git merge main` or `git rebase main`.
Also, keep the data in sync with the production environment by using `upsun env:sync`.
## 6. Optional: Use a third-party Git provider
When you choose to use a third-party Git hosting service,
the Upsun Git repository becomes a read-only mirror of the third-party repository.
All your changes take place in the third-party repository.
Add an integration to your existing third-party repository:
- [BitBucket](/integrations/source/bitbucket.md)
- [GitHub](/integrations/source/github.md)
- [GitLab](/integrations/source/gitlab.md)
# Deploy Symfony on Upsun [Get started](https://docs.upsun.com/get-started/stacks/symfony/get-started.html)
Upsun is the official [Symfony](https://symfony.com/) PaaS.
This guide provides instructions for deploying, and working with, Symfony on Upsun.
## Before you begin
You need:
- [Git](https://git-scm.com/downloads).
Git is the primary tool to manage everything your app needs to run.
Push commits to deploy changes and control configuration through YAML files.
These files describe your infrastructure, making it transparent and version-controlled.
- A Upsun account.
If you don't already have one, [register for a trial account](https://auth.upsun.com/register).
You can sign up with an email address or an existing GitHub, Bitbucket, or Google account.
If you choose one of these accounts, you can set a password for your Upsun account later.
- The [Symfony CLI](https://symfony.com/download).
This lets you interact with your project from the command line.
You can also do most things through the [Web Console](/administration/web/_index.md).
Note
The Symfony CLI wraps the Upsun CLI with added features related to Symfony.
So when using Symfony, you can replace upsun <command> by symfony upsun:<command> in all of your commands.
## 1. Create your Symfony app
To get familiar with Upsun, create a new Symfony project from scratch.
The present tutorial uses the [Symfony Demo](https://symfony.com/doc/current/setup.html#the-symfony-demo-application) app as an example :
```bash {location="Terminal"}
symfony new PROJECT_NAME --demo --upsun
cd PROJECT_NAME
```
The `--demo` flag pulls the [Symfony Demo skeleton](https://github.com/symfony/demo).
The `--upsun` flag automatically generates the Upsun configuration file.
Note
Alternatively, you can deploy an existing Symfony project.
To do so, follow these steps:
To generate a sensible default Upsun configuration,
run the following command from within the project’s directory:
Terminal
symfony project:init --upsun
This generates the .upsun/config.yaml and php.ini configuration files.
## 2. Create your Upsun project
To create a project on Upsun, run the following command from within the project's directory:
```bash {location="Terminal"}
symfony upsun:create --title PROJECT_TITLE --set-remote
```
The `--set-remote` flag sets the new project as the remote for this repository.
Tip
You can link any repository to an existing Upsun project using the following command:
Terminal
symfony upsun:set-remote PROJECT_ID
## 3. Deploy your project
To deploy your project, run the following command:
```bash {location="Terminal"}
symfony upsun:deploy
```
During deployment, the logs from the Upsun API are displayed in your terminal so you can monitor progress.
To stop the display of the logs **without interrupting the deployment**,
use `CTRL+C` in your terminal.
To go back to displaying the logs, run `symfony upsun:activity:log`.
Congratulations, your first Symfony app has been deployed on Upsun!
Tip
Now that your app is deployed in production mode,
you can define a custom domain for your live website.
To do so, see how to set up a custom domain on Upsun,
or run the following command:
Terminal
symfony upsun:domain:add YOUR_DOMAIN
## 4. Make changes to your project
Now that your project is deployed, you can start making changes to it.
For example, you might want to fix a bug or add a new feature.
In your project, the main branch always represents the production environment.
Other branches are for developing new features, fixing bugs, or updating the infrastructure.
To make changes to your project, follow these steps:
1. Create a new environment (a Git branch) to make changes without impacting production:
```bash {location="Terminal"}
symfony upsun:branch feat-a
```
This command creates a new local `feat-a` Git branch based on the main Git branch,
and activates a related environment on Upsun.
The new environment inherits the data (service data and assets) of its parent environment (the production environment here).
2. Make changes to your project.
For example, if you created a Symfony Demo app,
edit the `templates/default/homepage.html.twig` template and make the following visual changes:
```html {location="templates/default/homepage.html.twig"}
{% block body %}
-
{{ 'title.homepage'|trans|raw }}
+
Welcome to the Upsun Demo
```
3. Add and commit your changes:
```bash {location="Terminal"}
git commit -a -m "Update text"
```
4. Deploy your changes to the `feat-a` environment:
```bash {location="Terminal"}
symfony upsun:deploy
```
Note that each environment has its own domain name.
To view the domain name of your new environment, run the following command:
```bash {location="Terminal"}
symfony upsun:url --primary
```
5. Iterate by changing the code, committing, and deploying.
When satisfied with your changes, merge them to the main branch, deploy,
and remove the feature branch:
```bash {location="Terminal"}
git checkout main
git merge feat-a
symfony environment:delete feat-a
git branch -d feat-a
symfony upsun:deploy
```
Note that deploying to production is fast because the image built for the `feat-a` environment is reused.
For a long running branch, keep the code up-to-date with the main branch by using `git merge main` or `git rebase main`.
Also, keep the data in sync with the production environment by using `symfony upsun:env:sync`.
## 5. Optional: Use a third-party Git provider
When you choose to use a third-party Git hosting service,
the Upsun Git repository becomes a read-only mirror of the third-party repository.
All your changes take place in the third-party repository.
Add an integration to your existing third-party repository:
- [BitBucket](/integrations/source/bitbucket.md)
- [GitHub](/integrations/source/github.md)
- [GitLab](/integrations/source/gitlab.md)
# Manage resources [Resource configuration](https://docs.upsun.com/manage-resources/adjust-resources.html)
When you first deploy your project, or add a new app or service to it,
Upsun allocates [default resources](/manage-resources/resource-init.md#default-resources) to each of your containers.
If you don't want to use those default resources, define a different [resource initialization strategy](/manage-resources/resource-init#specify-a-resource-initialization-strategy).
After the initial deployment, or if you opt for the `Manual` [resource initialization strategy](/manage-resources/resource-init#specify-a-resource-initialization-strategy),
you can adjust container resources manually.
To do so, follow the instructions on this page.
Upsun allows you to configure resources (CPU, RAM, and disk) per environment for each app and service.
You can also add instances for each app depending on your needs.
For example, you can scale vertically and allocate more resources to your production and staging environments
than to your development environments.
This flexibility allows you to optimize performance and costs.
You can also scale horizontally if your apps are struggling with high load, or if you're expecting a traffic spike,
by adding more instances for your apps and workers.
To set resources for each of your apps and services,
you can use the Upsun CLI interactive prompts, or run commands manually.
Interactive prompts:
Run the upsun resources:set command, and follow the prompts to set resources for each app and service.
Note
For further guidance on how to set resources using the CLI, run the upsun resources:set --help command.
Note that if the deployment fails after you’ve run upsun resources:set,
you may need to set the resources again.
After you’ve set resources, your environment is redeployed,
which causes a short downtime.
Manual commands:
Run the resources:set command using the following CLI options:
CLI option
Description
size
Allows you to define how much CPU you want to allocate to each app or service.The amount of CPU then determines how much RAM is also allocated, based on the container profile.
disk
Allows you to define how much disk/storage you want to allocate to each app or service.
Example 1:
The following command allocates 0.1 CPU to the frontend app, 0.25 CPU to the backend app, and 1 CPU to the database service.
The amount of RAM these settings translate into depends on each container profile.
You can also use wildcards. For example, if you have two apps named frontend and backend,
you could allocate the same CPU and RAM combination to both by using the following command:
Terminal
upsun resources:set --size '*end:0.1'
Open your project.
Click the Configure resources button in the project card or the App & Services panel:
For each app and service, select a CPU & RAM combination, and enter the amount of disk/storage you want to allocate.
Note
The values from the CPU & RAM menu depend on the container profile of each instance.
If you deploy several instances of your app, the selected CPU & RAM combination isn’t divided between those instances.
Each instance benefits from the full, selected CPU & RAM.
Click Save.
You environment is redeployed, which causes a short downtime.
## Horizontal scaling
For apps and workers, you can also define how many instances you want to deploy.
To do so, follow these steps:
Note
When you have several instances of an app, the Upsun router randomly distributes requests to available instances.
For example, to scale all your apps to 3 instances, run the following command:
Terminal
upsun resources:set --count '*:3'
Note
For further guidance on how to set resources using the CLI, run the upsun resources:set --help command.
After you’ve set the number of instances for your apps and workers, your environment is redeployed.
If you’ve made no other changes, this redeployment causes no downtime.
If the redeployment fails after you’ve run upsun resources:set,
you may need to set the resources again.
Open your project.
Click the Configure resources button in the project card or the App & Services panel:
For each of your apps and workers, select the number of instances you want to deploy.
Note
If you deploy several instances of your app, the selected CPU & RAM combination isn’t divided between those instances.
Each instance benefits from the full, selected CPU & RAM.
Click Save.
Your environment is redeployed.
If you’ve only made changes to the number of instances for your apps and workers,
this redeployment causes no downtime.
## Advanced: Container profiles
By default, Upsun allocates a container profile to each app and service depending on the range of resources it's expected to need.
Each container profile gives you access to a specific list of CPU and RAM combinations.
Using the Upsun CLI or Console, you can then pick a CPU and RAM combination for each of your apps and services.
There are four container profiles available: `HIGH_CPU`, `BALANCED`, `HIGH_MEMORY`, and `HIGHER_MEMORY`.
The following table displays the different CPU and RAM combinations each container profile provides:
| CPU | `HIGH_CPU` | `BALANCED` | `HIGH_MEMORY` | `HIGHER_MEMORY` |
| ---- | ------------ | ---------- | ------------- | --------------- |
| 0.1 | 64 MB | 352 MB | 448 MB | 864 MB |
| 0.25 | 128 MB | 640 MB | 832 MB | 1472 MB |
| 0.5 | 224 MB | 1088 MB | 1408 MB | 2368 MB |
| 1 | 384 MB | 1920 MB | 2432 MB | 3840 MB |
| 2 | 704 MB | 2800 MB | 4032 MB | 6336 MB |
| 4 | 1216 MB | 4800 MB | 6720 MB | 10496 MB |
| 6 | 1728 MB | 6080 MB | 9024 MB | 14080 MB |
| 8 | 2240 MB | 7296 MB | 11200 MB | 17408 MB |
You can check which container profile is set for an app or service in your project from the Console.
To do so, navigate to your environment and select the app or service in the tree on the left-hand side:

For information on resource-related costs, see the [Upsun pricing page](https://upsun.com/pricing/).
### Default container profiles
The following table shows the default container profiles Upsun applies when first deploying your project.
| Container | Default profile |
|-------------------------|------------------|
| Chrome Headless | HIGH_CPU |
| ClickHouse | HIGH_MEMORY |
| .NET | HIGH_CPU |
| Elasticsearch | HIGH_MEMORY |
| Elasticsearch Premium | HIGH_MEMORY |
| Elixir | HIGH_CPU |
| Go | HIGH_CPU |
| Gotenberg | HIGH_MEMORY |
| InfluxDB | HIGH_MEMORY |
| Java | HIGH_MEMORY |
| Kafka | HIGH_MEMORY |
| Lisp | HIGH_CPU |
| MariaDB | HIGH_MEMORY |
| Memcached | BALANCED |
| MongoDB | HIGH_MEMORY |
| MongoDB Premium | HIGH_MEMORY |
| Network Storage | HIGH_MEMORY |
| NodeJS | HIGH_CPU |
| OpenSearch | HIGH_MEMORY |
| Oracle Java | HIGH_MEMORY |
| Oracle MySQL | HIGH_MEMORY |
| PHP | HIGH_CPU |
| PostgreSQL | HIGH_MEMORY |
| Python | HIGH_CPU |
| RabbitMQ | HIGH_MEMORY |
| Redis ephemeral | BALANCED |
| Redis persistent | BALANCED |
| Ruby | HIGH_CPU |
| Rust | HIGH_CPU |
| Solr | HIGH_MEMORY |
| Varnish | HIGH_MEMORY |
| Vault KMS | HIGH_MEMORY |
### Adjust a container profile
In most cases, it's best not to adjust container profiles.
As a best practice, Upsun recommends adjusting the profile of a container **only if the CPU/RAM ratio doesn’t match how the container scales**,
taking into account both production and preview (staging and development) environments.
To adjust a container profile, amend the value of the `container_profile` key in your configuration:
```yaml {configFile="app"}
applications:
APP_NAME:
container_profile: HIGH_MEMORY
services:
SERVICE_NAME:
type: SERVICE_TYPE:VERSION
container_profile: HIGHER_MEMORY
```
# Deploy Express on Upsun [Add a database](https://docs.upsun.com/get-started/stacks/express/add-database.html)
Once your Express app has been deployed on Upsun, you might want to add a service to it.
Upsun projects already include a [variety of managed services](/add-services.html#available-services), so you don’t have to subscribe to an external cache or search-engine services.
As these services are included in your project, you can manage them through Git.
They’re backed up along with the rest of your project.
You can add new services and manage existing service configurations from your `.upsun/config.yaml` file.
For example, to add a [MariaDB database engine](/add-services/mysql.html) to your Express project, complete the following steps:
## 1. Create a new branch for testing
To create a new branch, run the following command:
```bash {location="Terminal"}
upsun environment:branch add-mysql-database
```
## 2. Add a MariaDB service
Configure the MariaDB service by adding a `database` service to your `.upsun/config.yaml` file:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: "nodejs:20"
[...]
services:
database:
type: mariadb:11.4
```
To connect the service to your application (``myapp``), add the following relationship:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: "nodejs:20"
[...]
relationships:
database:
services:
database:
type: mariadb:11.4
```
Commit your change:
```bash {location="Terminal"}
git commit -am "adding MariaDb database service"
upsun push
```
Upsun now reads your configuration files and deploys your project using [default container resources](/manage-resources/resource-init.md).
If you don't want to use those default resources,
define your own [resource initialization strategy](/manage-resources/resource-init#specify-a-resource-initialization-strategy),
or [amend those default container resources](/manage-resources/adjust-resources.md) after your project is deployed.
## 3. Connect to the service
To configure your Express app so it uses your new database,
you need a Node.s module named `mysql2`.
To install it, run the following command:
```bash {location="Terminal"}
npm install mysql2
```
Wherever your application code attemps to connect to the database service,
Upsun will automatically generate environment variables containing connection credentials as a function of the relationship name.
In this example, the MariaDB service access is granted to the application container via the relationship `database`.
Upsun will therefore generate the variable `DATABASE_HOST` (among many others), using this name.
Here's an example of how this credential variable naming convention is used to connect to a MariaDB service:
```javascript {location="index.js"}
const express = require('express')
const app = express()
const mysql = require("mysql2/promise");
const port = (process.env.PORT || '3000');
function openConnection() {
return mysql.createConnection({
host: process.env.DATABASE_HOST,
port: process.env.DATABASE_PORT,
user: process.env.DATABASE_USERNAME,
password: process.env.DATABASE_PASSWORD,
database: process.env.DATABASE_DATABASE
});
}
function createTable(connection) {
return connection.execute(
`CREATE TABLE IF NOT EXISTS upsuninfo (
uid INT(10) NOT NULL AUTO_INCREMENT,
username VARCHAR(64) NULL DEFAULT NULL,
departname VARCHAR(128) NULL DEFAULT NULL,
created DATE NULL DEFAULT NULL,
PRIMARY KEY (uid)
) DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;`
);
}
function insertData(connection) {
return connection.execute(
"INSERT INTO upsuninfo (username, departname, created) VALUES ('upsun', 'Deploy Friday', '2023-09-29')"
);
}
function readData(connection) {
return connection.query("SELECT * FROM upsuninfo");
}
function dropTable(connection) {
return connection.execute("DROP TABLE upsuninfo");
}
// Define the main route.
app.get('/', async function(req, res){
// Connect to MariaDB.
const connection = await openConnection();
await createTable(connection);
await insertData(connection);
const [rows] = await readData(connection);
const droppedResult = await dropTable(connection);
// Make the output.
const outputString = `Hello, World! - A simple Express web framework template for Upsun
MariaDB Tests:
* Connect and add row:
- Row ID (1): ${rows[0].uid}
- Username (upsun): ${rows[0].username}
- Department (Deploy Friday): ${rows[0].departname}
- Created (2023-09-29): ${rows[0].created}
* Delete row:
- Status (0): ${droppedResult[0].warningStatus}`;
res.set('Content-Type', 'text/plain');
res.send(outputString);
});
// Get PORT and start the server
app.listen(port, function() {
console.log(`Listening on port ${port}`)
});
```
Commit and deploy your changes:
```bash {location="Terminal"}
git add package.json package-lock.json index.js && git commit -m "adding MariaDb database service"
upsun push
upsun environment:url --primary
```
## 4. Merge to production
When satisfied with your changes, merge them to the main branch:
```bash {location="Terminal"}
upsun merge
```
## 5. Remove the feature branch
Then, remove the feature branch:
```bash {location="Terminal"}
upsun checkout main
git pull upsun main
upsun environment:delete add-mysql-database
git fetch --prune
```
Note
When the environment:delete CLI command is run, the CLI suggests you deactivate and delete your add-mysql-database environment.
Make sure you opt in.
## Tips & Tricks
You can get your project's relationship information using the following command:
```bash {location="Terminal"}
upsun relationships
...
database:
-
username: user
scheme: mysql
service: mariadb
fragment: null
ip: 198.12.123.45
hostname: abcdefghijklm1234567890123.mariadb.service._..platformsh.site
public: false
cluster: abcdefgh1234567-add-mysql-database-abcd123
host: mariadb.internal
rel: mysql
query:
is_master: true
path: main
password: ''
type: 'mariadb:10.6'
port: 3306
host_mapped: false
url: 'mysql://user:@mariadb.internal:3306/main'
```
# Deploy Strapi on Upsun [Add a database](https://docs.upsun.com/get-started/stacks/strapi/add-database.html)
Once Your Strapi application has been deployed on Upsun, you might want to add and configure a service to your application.
This guide will show you how to provision and connect to two different databases on Upsun:
- PostgreSQL
- Oracle MySQL
## 1. Branch
Like all updates to your Upsun projects, first create a new dedicated environment to test this change.
```bash
git checkout -b upgrade-db
```
## 2. Install the Node.js package
## 5. Update `.environment`
When you previously ran `upsun project:init`, the command generated some Strapi-specific environment variables:
```bash {location=".environment"}
# Set Strapi-specific environment variables
export DATABASE_HOST="$DB_HOST"
export DATABASE_PORT="$DB_PORT"
export DATABASE_NAME="$DB_PATH"
export DATABASE_USERNAME="$DB_USERNAME"
export DATABASE_PASSWORD="$DB_PASSWORD"
export DATABASE_SCHEME="$DB_SCHEME"
# Set secrets needed by Strapi, if they are not set
# Prefer setting these as project secret variables with upsun variable:create env:SECRET_NAME --sensitive=true
if [[ -z "$ADMIN_JWT_SECRET" ]]; then
export ADMIN_JWT_SECRET="$PLATFORM_PROJECT_ENTROPY"
fi
if [[ -z "$JWT_SECRET" ]]; then
export JWT_SECRET="$PLATFORM_PROJECT_ENTROPY"
fi
if [[ -z "$API_TOKEN_SALT" ]]; then
export API_TOKEN_SALT="$PLATFORM_PROJECT_ENTROPY"
fi
if [[ -z "$APP_KEYS" ]]; then
export APP_KEYS="$PLATFORM_PROJECT_ENTROPY"
fi
```
Upsun will actually generate service credentials automatically for you in the runtime container, so we don't need the first half of this file anymore.
Remove the first block (pertaining to `DATABASE` credentials).
Then, add a single additional variable that will set the `DATABASE_CLIENT` variable at the appropriate time:
# Set secrets needed by Strapi, if they are not set# Prefer setting these as project secret variables with upsun variable:create env:SECRET_NAME --sensitive=trueif[[ -z "$ADMIN_JWT_SECRET"]];thenexportADMIN_JWT_SECRET="$PLATFORM_PROJECT_ENTROPY"fiif[[ -z "$JWT_SECRET"]];thenexportJWT_SECRET="$PLATFORM_PROJECT_ENTROPY"fiif[[ -z "$API_TOKEN_SALT"]];thenexportAPI_TOKEN_SALT="$PLATFORM_PROJECT_ENTROPY"fiif[[ -z "$APP_KEYS"]];thenexportAPP_KEYS="$PLATFORM_PROJECT_ENTROPY"fi# Switch to configure to the production database service _only_ at deploy time.if[[ -z "$PLATFORM_ENVIRONMENT"]];thenexportDATABASE_CLIENT="postgres"fi
.environment
# Set secrets needed by Strapi, if they are not set# Prefer setting these as project secret variables with upsun variable:create env:SECRET_NAME --sensitive=trueif[[ -z "$ADMIN_JWT_SECRET"]];thenexportADMIN_JWT_SECRET="$PLATFORM_PROJECT_ENTROPY"fiif[[ -z "$JWT_SECRET"]];thenexportJWT_SECRET="$PLATFORM_PROJECT_ENTROPY"fiif[[ -z "$API_TOKEN_SALT"]];thenexportAPI_TOKEN_SALT="$PLATFORM_PROJECT_ENTROPY"fiif[[ -z "$APP_KEYS"]];thenexportAPP_KEYS="$PLATFORM_PROJECT_ENTROPY"fi# Switch to configure to the production database service _only_ at deploy time.if[[ -z "$PLATFORM_ENVIRONMENT"]];thenexportDATABASE_CLIENT="mysql"fi
## 6. Push to the environment
Commit and push the changes to the Upsun environment:
```bash
git commit -am "Add a new service"
git push origin upgrade-db
```
Note
If you are using Upsun as your primary remote, you can use the upsun branch and upsun push commands directly.
If instead you had already set up an integration to GitHub, GitLab or Bitbucket, make sure to open a pull/merge request to judge the revision.
# Deploy Symfony on Upsun [Symfony integration](https://docs.upsun.com/get-started/stacks/symfony/integration.html)
Symfony has a special integration with Upsun that makes it easier to use Upsun for Symfony projects.
**When using the Symfony integration, you are contributing financially to the Symfony project.**
The Symfony integration is automatically enabled when:
- You run the `symfony new` command with the `--upsun` option
- You run `symfony project:init --upsun` on an existing project to automatically
generate the Upsun configuration
If you already have a Upsun configuration without the Symfony
integration, enable it by adding the following configuration:
```yaml {configFile="app"}
applications:
app:
hooks:
build: |
set -x -e
curl -fs https://get.symfony.com/cloud/configurator | bash
# ...
```
The **configurator** enables the following integration:
- It installs some helper scripts that you can use as the [default build and deploy hook scripts](#hooks):
- [`symfony-build`](#symfony-build)
- [`symfony-deploy`](#symfony-deploy)
- [`php-ext-install`](#php-ext-install)
- It adds some [extra tools](#tools)
- It defines [additional infrastructure environment
variables](./environment-variables#symfony-environment-variables) and
[environment variables for all
services](./environment-variables#service-environment-variables)
## Tools
The **configurator** (`curl -fs https://get.symfony.com/cloud/configurator | bash`) is a script specially crafted for Upsun.
It ensures that projects are always using the latest version of the following tools:
- [croncape](./crons#use-croncape) for cron feedback
- [Symfony CLI](https://symfony.com/download)
- [Composer](https://getcomposer.org/download/)
## Hooks
The `hooks` section defines the scripts that Upsun runs at specific times of an application lifecycle:
- The [build hook](/create-apps/hooks/hooks-comparison.md#build-hook) is run during the build process
- The [deploy hook](/create-apps/hooks/hooks-comparison.md#deploy-hook) is run during the deployment process
- The [post-deploy hook](/create-apps/hooks/hooks-comparison.md#post-deploy-hook) is run after the deploy hook,
once the application container starts accepting connections
Here's the default `hooks` section optimized for Symfony projects:
```yaml {configFile="app"}
applications:
app:
hooks:
build: |
set -x -e
curl -s https://get.symfony.com/cloud/configurator | bash
symfony-build
deploy: |
set -x -e
symfony-deploy
```
Warning
As each hook is executed as a single script, a hook is considered as failed only if the final command fails.
To have your hooks fail on the first failed command, start your scripts with set -e.
For more information, see [Hooks](/create-apps/hooks/hooks-comparison).
To gain a better understanding of how hooks relate to each other when building and deploying an app,
see the [Upsun philosophy](/learn/overview/philosophy.md).
Tip
During the deploy or post_deploy hooks, you can execute actions for a specific environment type only.
To do so, in your .upsun/config.yamlfile,
use the PLATFORM_ENVIRONMENT_TYPEenvironment variable) in a condition:
.upsun/config.yaml
applications:myapp:hooks:deploy:| if [ "PLATFORM_ENVIRONMENT_TYPE" != "production" ]; then
symfony console app:dev:anonymize
fi
### symfony-build
**symfony-build** is the script that builds a Symfony app in an optimized way for Upsun.
Use it as the main build script in your `build` hook.
**symfony-build** performs the following actions:
- Removes the development frontend file (Symfony <4)
- Installs PHP extensions through the [`php-ext-install` script](#php-ext-install)
- Installs application dependencies using Composer
- Optimizes the autoloader
- Builds the Symfony cache in an optimized way to limit the time it takes to deploy
- Installs the JavaScript dependencies via npm or Yarn
- Builds the production assets using Encore
To override the flags used by Composer, use the `$COMPOSER_FLAGS` environment variable:
```yaml {configFile="app"}
applications:
myapp:
hooks:
build: |
set -x -e
curl -s https://get.symfony.com/cloud/configurator | bash
COMPOSER_FLAGS="--ignore-platform-reqs" symfony-build
```
When installing dependencies, the script automatically detects if the app is using npm or Yarn.
To disable the JavaScript dependencies and asset building,
set `NO_NPM` or `NO_YARN` to `1` depending on your package manager.
To customize Node/npm/Yarn behaviors,
prefix the `symfony-build` script with the following environment variables:
- `NODE_VERSION`: to pinpoint the Node version that nvm is going to install.
The default value is `--lts`.
- `YARN_FLAGS`: flags to pass to `yarn install`.
There is no default value.
### symfony-deploy
Use **symfony-deploy** as the main deploy script in the `deploy` hook.
It only works if you're using the [`symfony-build` script](#symfony-build) in your `build` hook.
**symfony-deploy** performs the following actions:
- Replaces the Symfony cache with the cache generated during the build hook
- Migrates the database when the Doctrine migration bundle is used
### php-ext-install
You can use the **php-ext-install** script to compile and install PHP extensions
not provided out of the box by Upsun,
or when you need a specific version of an extension.
The script is written specifically for Upsun to ensure fast and reliable setup during the build step.
**php-ext-install** currently supports three ways of fetching sources:
- From [PECL](https://pecl.php.net/): `php-ext-install redis 5.3.2`
- From a URL: `php-ext-install redis https://github.com/phpredis/phpredis/archive/5.3.2.tar.gz`
- From a Git repository: `php-ext-install redis https://github.com/phpredis/phpredis.git 5.3.2`
To ensure your app can be built properly, run `php-ext-install` after the [configurator](#tools)
but before [symfony-build](#symfony-build):
```yaml {configFile="app"}
applications:
myapp:
hooks:
build: |
set -x -e
curl -s https://get.symfony.com/cloud/configurator | bash
php-ext-install redis 5.3.2
symfony-build
```
When installing [PECL](https://pecl.php.net/) PHP extensions, you can configure
them directly as *variables* instead:
```yaml {configFile="app"}
applications:
myapp:
variables:
php-ext:
redis: 5.3.2
```
Note
The source code is cached between builds so compilation is skipped if it’s already been done.
Changing the source of downloads or the version invalidates this cache.
### Advanced Node configuration
If you need to use the Node installation setup by [symfony-build](#symfony-build),
use the following configuration:
```yaml {configFile="app"}
applications:
myapp:
hooks:
build: |
set -x -e
curl -s https://get.symfony.com/cloud/configurator | bash
symfony-build
# Setup everything to use the Node installation
unset NPM_CONFIG_PREFIX
export NVM_DIR=${SPLATFORM_APP_DIR}/.nvm
set +x && . "${NVM_DIR}/nvm.sh" use --lts && set -x
# Starting from here, everything is setup to use the same Node
yarn encore dev
```
If you want to use two different Node versions,
use the following configuration instead:
```yaml {configFile="app"}
applications:
myapp:
hooks:
build: |
set -x -e
curl -s https://get.symfony.com/cloud/configurator | bash
symfony-build
cd web/js_app
unset NPM_CONFIG_PREFIX
export NVM_DIR=${PLATFORM_APP_DIR}/.nvm
NODE_VERSION=8 yarn-install
# Setup everything to use the Node installation
set +x && . "${NVM_DIR}/nvm.sh" use 8 && set -x
# Starting from here, everything is setup to use Node 8
yarn build --environment=prod
```
# Deploy Laravel on Upsun [Configure environment variables](https://docs.upsun.com/get-started/stacks/laravel/environment-variables.html)
By default, Upsun exposes some [environment variables](/development/variables/use-variables#use-provided-variables).
Laravel relies heavily on environment variables to configure application services (such as the database or the mailer).
Therefore, the default configuration generated by `upsun project:init` includes
the [environment variables for all the services](#service-environment-variables) connected to your app in the `.environment` file.
Tip
You can tweak the .environment configuration to fit your needs and add specific project-level variables.
You may need a variable to change per environment. If so, use the upsun variable command to add all the needed per-environment variables.
## Default environment variables
Upsun automatically exposes [environment variables](/development/variables/use-variables#use-provided-variables)
about the app and its infrastructure.
Assuming that MySQL, PostgreSQL, and Redis services have been added to your environment,
and that the app has been granted access to those services via the following [relationships](/create-apps/app-reference/single-runtime-image#relationships):
```yaml {configFile="app"}
applications:
myapp:
[...]
relationships:
mysql: ...
postgresql: ...
redis: ...
```
You can transpose these variables to set up Laravel's default configuration in a `.environment` file:
```bash {configFile="env"}
# Set MySQL database environment variables
export DB_HOST="$MYSQL_HOST"
export DB_PORT="$MYSQL_PORT"
export DB_PATH="$MYSQL_PATH"
export DB_USERNAME="$MYSQL_USERNAME"
export DB_PASSWORD="$MYSQL_PASSWORD"
export DB_SCHEME="$MYSQL_SCHEME"
export DATABASE_URL="${DB_SCHEME}://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_PATH}"
# Or for PostgreSQL
export DB_HOST="$POSTGRESQL_HOST"
export DB_PORT="$POSTGRESQL_PORT"
export DB_PATH="$POSTGRESQL_PATH"
export DB_USERNAME="$POSTGRESQL_USERNAME"
export DB_PASSWORD="$POSTGRESQL_PASSWORD"
export DB_SCHEME="$POSTGRESQL_SCHEME"
export DATABASE_URL="${DB_SCHEME}://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_PATH}"
# Set Laravel-specific environment variables
export DB_CONNECTION="$DB_SCHEME"
export DB_DATABASE="$DB_PATH"
# Set Cache environment variables
export CACHE_HOST="$REDIS_HOST"
export CACHE_PORT="$REDIS_PORT"
export CACHE_SCHEME="$REDIS_SCHEME"
export CACHE_URL="${CACHE_SCHEME}://${CACHE_HOST}:${CACHE_PORT}"
# Set Redis environment variables
export REDIS_URL="$CACHE_URL"
```
## Service environment variables
Each exposed environment variable is prefixed by the relationship name.
For example, if you have the following relationships in your configuration:
```yaml {configFile="app"}
applications:
myapp:
relationships:
database:
service: "securitydb"
endpoint: "postgresql"
```
The environment variables for the database service is prefixed by `DATABASE_`,
which is the upper-cased version of the key defined in the relationship.
For example, you could have a `DATABASE_URL` environment variable.
Note
Environment variables aren’t exposed when the build hook script is running,
as services aren’t available during the build process.
To add specific variables available during the build, run upsun variable:create.
### Emails
Upsun provides a SMTP service for sending emails.
To configure email in Laravel, add the following mapping to your `.environment` file:
```bash {configFile="env"}
# Email
export MAIL_MAILER="smtp"
export MAIL_HOST="${PLATFORM_SMTP_HOST}"
export MAIL_PORT="25"
```
### HTTP
If your project has multiple apps,
the configuration is exposed via the following environment variables
(where `SOME_SERVICE` is the upper-cased version of the key defined in the relationship):
- `SOME_SERVICE_URL`: The full URL of the service
- `SOME_SERVICE_IP`: The HTTP service IP
- `SOME_SERVICE_PORT`: The HTTP service port
- `SOME_SERVICE_SCHEME`: The HTTP service scheme
- `SOME_SERVICE_HOST`: The HTTP service host
### MySQL/MariaDB
The [MySQL/MariaDB](/add-services/mysql) configuration is exposed via the following environment variables
(where `DATABASE` is the upper-cased version of the key defined in the relationship above):
- `DATABASE_URL`: The database URL (in PHP or Go format depending on your app)
- `DATABASE_SERVER`: The database server
- `DATABASE_DRIVER`: The database driver
- `DATABASE_VERSION`: The database version
- `DATABASE_HOST`: The database host
- `DATABASE_PORT`: The database port
- `DATABASE_NAME`: The database name
- `DATABASE_DATABASE`: Alias for `DATABASE_NAME`
- `DATABASE_USERNAME`: The database username
- `DATABASE_PASSWORD`: The database password
Tip
The database version and a default charset are included in the database URL.
To override them, use the DATABASE_VERSION and DATABASE_CHARSET environment variables respectively.
### PostgreSQL
The [PostgreSQL](/add-services/postgresql) configuration is exposed via the following environment variables
(where `DATABASE` is the upper-cased version of the key defined in the relationship):
- `DATABASE_URL`: The database URL (in PHP or Go format depending on your app)
- `DATABASE_SERVER`: The database server
- `DATABASE_DRIVER`: The database driver
- `DATABASE_VERSION`: The database version
- `DATABASE_HOST`: The database host
- `DATABASE_PORT`: The database port
- `DATABASE_NAME`: The database name
- `DATABASE_DATABASE`: Alias for `DATABASE_NAME`
- `DATABASE_USERNAME`: The database username
- `DATABASE_PASSWORD`: The database password
Tip
The database version and a default charset are included in the database URL.
To override them, use the DATABASE_VERSION and DATABASE_CHARSET environment variables respectively.
### Redis
The [Redis](/add-services/redis) configuration is exposed via the following environment variables
(where `REDIS` is the upper-cased version of the key defined in the relationship):
- `REDIS_URL`: The Redis URL
- `REDIS_HOST`: The Redis host
- `REDIS_PORT`: The Redis port
- `REDIS_SCHEME`: The Redis scheme
You can specify the Redis client in your `.environment` file:
```bash {configFile="env"}
export REDIS_CLIENT="phpredis"
```
### Memcached
The [Memcached](/add-services/memcached) configuration is exposed via the following environment variables
(where `CACHE` is the upper-cased version of the key defined in the relationship):
- `CACHE_HOST`
- `CACHE_PORT`
- `CACHE_IP`
### Elasticsearch
The [Elasticsearch](/add-services/elasticsearch) configuration is exposed via the following environment variables
(where `ELASTICSEARCH` is the upper-cased version of the key defined in the relationship):
- `ELASTICSEARCH_URL`: The full URL of the Elasticsearch service
- `ELASTICSEARCH_HOST`: The Elasticsearch host
- `ELASTICSEARCH_PORT`: The Elasticsearch port
- `ELASTICSEARCH_SCHEME`: The Elasticsearch protocol scheme (`http` or `https`)
### RabbitMQ
The [RabbitMQ](/add-services/rabbitmq) configuration is exposed via the following environment variables
(where `RABBITMQ` is the upper-cased version of the key defined in the relationship):
- `RABBITMQ_URL`: The RabbitMQ standardized URL
- `RABBITMQ_SERVER`: The RabbitMQ server
- `RABBITMQ_HOST`: The RabbitMQ host
- `RABBITMQ_PORT`: The RabbitMQ port
- `RABBITMQ_SCHEME`: The RabbitMQ scheme
- `RABBITMQ_USER`: The RabbitMQ username
- `RABBITMQ_USERNAME`: The RabbitMQ username
- `RABBITMQ_PASSWORD`: The RabbitMQ password
### MongoDB
The [MongoDB](/add-services/mongodb) configuration is exposed via the following environment variables
(where `MONGODB` is the upper-cased version of the key defined in the relationship):
- `MONGODB_SERVER`
- `MONGODB_HOST`
- `MONGODB_PORT`
- `MONGODB_SCHEME`
- `MONGODB_NAME`
- `MONGODB_DATABASE`
- `MONGODB_USER`
- `MONGODB_USERNAME`
- `MONGODB_PASSWORD`
### InfluxDB
The [InfluxDB](/add-services/influxdb) configuration is exposed via the following environment variables
(where `TIMEDB` is the upper-cased version of the key defined in the relationship):
- `TIMEDB_SCHEME`
- `TIMEDB_HOST`
- `TIMEDB_PORT`
- `TIMEDB_IP`
### Kafka
The [Apache Kafka](/add-services/kafka) configuration is exposed via the following environment variables
(where `KAFKA` is the upper-cased version of the key defined in the relationship):
- `KAFKA_URL`
- `KAFKA_SCHEME`
- `KAFKA_HOST`
- `KAFKA_PORT`
- `KAFKA_IP`
# Deploy Symfony on Upsun [Configure environment variables](https://docs.upsun.com/get-started/stacks/symfony/environment-variables.html)
By default, Upsun exposes some [environment variables](/development/variables/use-variables#use-provided-variables).
If you're using the [Symfony integration](./integration),
more [infrastructure environment variables](#symfony-environment-variables) related to Symfony are defined.
As Symfony relies heavily on environment variables to configure application services (such as the database or the mailer DSN),
the Symfony integration automatically defines [environment variables for all the services](#service-environment-variables) connected to your app.
Tip
The code that defines these additional environment variables is part of the open-source Symfony CLI tool.
Check the code for infrastructure
and service environment variables on GitHub.
## Symfony environment variables
Upsun exposes [environment variables](/development/variables/use-variables#use-provided-variables)
about the app and its infrastructure.
The Symfony integration exposes more environment variables:
- `APP_ENV` is set to `prod` by default.
You can manually override this value for a preview environment
by setting the `SYMFONY_ENV` environment variable to `dev`, and remove it when done.
- `APP_DEBUG` is set to `0` by default.
You can manually override this value for a preview environment
by setting the `SYMFONY_DEBUG` environment variable to `1`, and remove it when done.
- `APP_SECRET` is set to the value of `PLATFORM_PROJECT_ENTROPY`, which is a random and unique value for all Upsun projects.
It overrides the value configured in the `.env` file of your app.
- `MAILFROM` is set to a random value.
This value is used as a `From` header when using [croncape](./crons#use-croncape).
- `SYMFONY_IS_WORKER` is set to `1` when the container is running in the context of a worker
(instead of the main application container).
- `SYMFONY_CACHE_DIR` (only available during the build hook execution):
The absolute path to a subdirectory of your build cache directory.
Note that the build cache directory is persisted between builds but **isn't** deployed.
It’s a good place to store build artifacts, such as downloaded files that can be reused between builds.
Tip
This directory is shared by all builds on all branches.
Make sure your build hook accounts for that.
If you need to clear the build cache directory, run the `symfony upsun:project:clear-build-cache` command.
- `SYMFONY_PROJECT_DEFAULT_ROUTE_URL` (only defined at **runtime**): The default endpoint serving your project.
Use this variable to avoid hard-coding domains that can be used to reach preview environments.
Parts of the URL are also exposed as their own variables using the following syntax:
`SYMFONY_PROJECT_DEFAULT_ROUTE_` followed by the name of the part (`SCHEME`, `DOMAIN`, `PORT`, and `PATH`).
Guessing the default endpoint can prove difficult for multi-routes or multi-app projects.
In such cases, the following preference order is used:
1. Project-wide route defined only by `{default}` or `{all}` (no path)
2. Project-wide route defined by `www.{default}` or `www.{all}` (no path)
3. Route for the **current application** including `{default}` or `{all}` (might include a path)
4. Route for the **current application** including `www.{default}` or `www.{all}` (might include a path)
5. First route for the current application
6. First route for the whole project
When several routes match a rule, the first one wins, the user order is kept. There's no preference regarding protocols.
Tip
If you have a multi-app project containing several publicly reachable apps,
you might need to determine the current application endpoint (for webhooks for example)
and the project endpoint (to send emails for example).
In this case, you can use an additional SYMFONY_APPLICATION_DEFAULT_ROUTE_* set of environment variables.
The same rules are applied to determine their value, but only routes matching the current application are evaluated.
## Service environment variables
When using the [Symfony integration](./integration), information about services
are exposed via environment variables.
To list all of the exposed environment variables, run the following command:
```bash
symfony ssh -- symfony var:export --multiline
```
Each exposed environment variable is prefixed by the relationship name.
For example, if you have the following [relationships](/create-apps/app-reference/single-runtime-image#relationships) in your configuration:
```yaml {configFile="app"}
applications:
myapp:
relationships:
database:
service: securitydb
endpoint: postgresql
```
The environment variables for the database service is prefixed by `DATABASE_`
which is the upper-cased version of the key defined in the relationship.
For example, you could have a `DATABASE_URL` environment variable.
Most environment variable names are derived from the relationship and service names.
But some are defined based on Symfony conventions, such as [`MAILER_DSN`](#emails).
Note
Environment variables aren’t exposed when the build hook script is running
as services aren’t available during the build process.
### Emails
The configuration is exposed via the following environment variables:
- `MAILER_ENABLED`: 1 if outgoing emails are enabled, 0 otherwise
- `MAILER_DSN`/`MAILER_URL`: The Symfony-compatible mailer URL
- `MAILER_HOST`: The SMTP server host
- `MAILER_PORT`: The SMTP server port
- `MAILER_TRANSPORT`: The SMTP transport mode (`smtp`)
- `MAILER_AUTH_MODE`: The SMTP auth mode (`plain`)
- `MAILER_USER`: The SMTP server user
- `MAILER_PASSWORD`: The SMTP server password
Symfony Mailer automatically uses the value of `MAILER_DSN`.
### HTTP
If your project has multiple apps,
the configuration is exposed via the following environment variables
(where `SOME_SERVICE` is the upper-cased version of the key defined in the relationship):
- `SOME_SERVICE_URL`: The full URL of the service
- `SOME_SERVICE_IP`: The HTTP service IP
- `SOME_SERVICE_PORT`: The HTTP service port
- `SOME_SERVICE_SCHEME`: The HTTP service scheme
- `SOME_SERVICE_HOST`: The HTTP service host
### MySQL/MariaDB
The [MySQL/MariaDB](/add-services/mysql) configuration is exposed via the following environment variables
(where `DATABASE` is the upper-cased version of the key defined in the relationship above):
- `DATABASE_URL`: The database URL (in PHP or Go format depending on your app)
- `DATABASE_SERVER`: The database server
- `DATABASE_DRIVER`: The database driver
- `DATABASE_VERSION`: The database version
- `DATABASE_HOST`: The database host
- `DATABASE_PORT`: The database port
- `DATABASE_NAME`: The database name
- `DATABASE_DATABASE`: Alias for `DATABASE_NAME`
- `DATABASE_USERNAME`: The database username
- `DATABASE_PASSWORD`: The database password
Tip
The database version and a default charset are included in the database URL.
To override them, use the DATABASE_VERSION and DATABASE_CHARSET environment variables respectively.
### PostgreSQL
The [PostgreSQL](/add-services/postgresql) configuration is exposed via the following environment variables
(where `DATABASE` is the upper-cased version of the key defined in the relationship):
- `DATABASE_URL`: The database URL (in PHP or Go format depending on your app)
- `DATABASE_SERVER`: The database server
- `DATABASE_DRIVER`: The database driver
- `DATABASE_VERSION`: The database version
- `DATABASE_HOST`: The database host
- `DATABASE_PORT`: The database port
- `DATABASE_NAME`: The database name
- `DATABASE_DATABASE`: Alias for `DATABASE_NAME`
- `DATABASE_USERNAME`: The database username
- `DATABASE_PASSWORD`: The database password
Tip
The database version and a default charset are included in the database URL.
To override them, use the DATABASE_VERSION and DATABASE_CHARSET environment variables respectively.
### Redis
The [Redis](/add-services/redis) configuration is exposed via the following environment variables
(where `REDIS` is the upper-cased version of the key defined in the relationship):
- `REDIS_URL`: The Redis URL
- `REDIS_HOST`: The Redis host
- `REDIS_PORT`: The Redis port
- `REDIS_SCHEME`: The Redis scheme
### Memcached
The [Memcached](/add-services/memcached) configuration is exposed via the following environment variables
(where `CACHE` is the upper-cased version of the key defined in the relationship):
- `CACHE_HOST`
- `CACHE_PORT`
- `CACHE_IP`
### Elasticsearch
The [Elasticsearch](/add-services/elasticsearch) configuration is exposed via the following environment variables
(where `ELASTICSEARCH` is the upper-cased version of the key defined in the relationship):
- `ELASTICSEARCH_URL`: The full URL of the Elasticsearch service
- `ELASTICSEARCH_HOST`: The Elasticsearch host
- `ELASTICSEARCH_PORT`: The Elasticsearch port
- `ELASTICSEARCH_SCHEME`: The Elasticsearch protocol scheme (`http` or `https`)
### Solr
The [Apache Solr](/add-services/solr) configuration is exposed via the following environment variables
(where `SOLR` is the upper-cased version of the key defined in the relationship):
- `SOLR_HOST`: The Solr host
- `SOLR_PORT`: The Solr port
- `SOLR_NAME`: The Solr name
- `SOLR_DATABASE`: An alias for `SOLR_NAME`
### RabbitMQ
The [RabbitMQ](/add-services/rabbitmq) configuration is exposed via the following environment variables
(where `RABBITMQ` is the upper-cased version of the key defined in the relationship):
- `RABBITMQ_URL`: The RabbitMQ standardized URL
- `RABBITMQ_SERVER`: The RabbitMQ server
- `RABBITMQ_HOST`: The RabbitMQ host
- `RABBITMQ_PORT`: The RabbitMQ port
- `RABBITMQ_SCHEME`: The RabbitMQ scheme
- `RABBITMQ_USER`: The RabbitMQ username
- `RABBITMQ_USERNAME`: The RabbitMQ username
- `RABBITMQ_PASSWORD`: The RabbitMQ password
### MongoDB
The [MongoDB](/add-services/mongodb) configuration is exposed via the following environment variables
(where `MONGODB` is the upper-cased version of the key defined in the relationship):
- `MONGODB_SERVER`
- `MONGODB_HOST`
- `MONGODB_PORT`
- `MONGODB_SCHEME`
- `MONGODB_NAME`
- `MONGODB_DATABASE`
- `MONGODB_USER`
- `MONGODB_USERNAME`
- `MONGODB_PASSWORD`
### InfluxDB
The [InfluxDB](/add-services/influxdb) configuration is exposed via the following environment variables
(where `TIMEDB` is the upper-cased version of the key defined in the relationship):
- `TIMEDB_SCHEME`
- `TIMEDB_HOST`
- `TIMEDB_PORT`
- `TIMEDB_IP`
### Kafka
The [Apache Kafka](/add-services/kafka) configuration is exposed via the following environment variables
(where `KAFKA` is the upper-cased version of the key defined in the relationship):
- `KAFKA_URL`
- `KAFKA_SCHEME`
- `KAFKA_HOST`
- `KAFKA_PORT`
- `KAFKA_IP`
# Deploy Laravel on Upsun [Set up Redis](https://docs.upsun.com/get-started/stacks/laravel/setup-redis.html)
With Laravel, you can use Redis to handle session storage, cache storage, and queues.
## 1. Add the Redis service
1. [Add the service](/add-services.md#add-a-service) to your app configuration using the `services` top-level key:
```yaml {configFile="app"}
services:
[...]
redis:
type: redis:7.0
```
2. To connect the service to your app, add the following relationship:
```yaml {configFile="app"}
applications:
myapp:
[...]
relationships:
redis:
services:
[...]
redis:
type: redis:7.0
```
## 2. Configure your Redis service
The [Redis](/add-services/redis) configuration is exposed via the following environment variables
(where `REDIS` is the upper-cased version of the key defined in the relationship):
- `REDIS_URL`: The Redis URL
- `REDIS_HOST`: The Redis host
- `REDIS_PORT`: The Redis port
- `REDIS_SCHEME`: The Redis scheme
If the relationship is named `redis`, Laravel automatically detects these variables and configure its own Redis driver the right way.
If not, you can map the variables in the `.environment` file.
You can specify the Redis client in your `.environment` file:
```bash {configFile="env"}
export REDIS_CLIENT="phpredis"
```
Note
If using phpredis, make sure you add redis in the list of PHP runtime extensions in your .upsun/config.yaml:
## 3. Store the Laravel cache in Redis
To enable cache storage in Redis, add the following environment variable to your `.environment` file:
```bash {configFile="env"}
export CACHE_STORE="redis"
```
## 4. Store Laravel sessions in Redis
Laravel relies on the `SESSION_DRIVER` variable to store sessions. Therefore, add the following environment variable to your `.environment` file:
```bash {configFile="env"}
export SESSION_DRIVER="redis"
```
## 5. Use Redis for Laravel queues
For a basic queueing system, configure the `QUEUE_CONNECTION` in your `.environment` file as follows:
```bash {configFile="env"}
export QUEUE_CONNECTION="redis"
```
For more information, see the [Laravel Queues documentation](https://laravel.com/docs/master/queues)
and Upsun's [Horizon configuration page](./laravel-horizon).
# Deploy Laravel on Upsun [Handle queues with Horizon](https://docs.upsun.com/get-started/stacks/laravel/laravel-horizon.html)
[Laravel Horizon](https://laravel.com/docs/master/horizon#main-content) provides an appealing dashboard and code-driven configuration
for your Laravel powered Redis queues.
Horizon allows you to monitor key metrics of your queue system,
such as job throughput, runtime, and job failures.
## 1. Add Laravel Horizon
1. To add Laravel Horizon, run the following command:
```bash {location="Terminal"}
composer require laravel/horizon && php artisan horizon:install
```
2. Add the `install` command to your `build` hook in your app configuration, so it's run on every deploy.
```yaml {configFile="app"}
applications:
myapp:
[...]
hooks:
build: |
set -eux
composer --no-ansi --no-interaction install --no-progress --prefer-dist --optimize-autoloader --no-dev
php artisan horizon:install
```
## 2. Create a worker to run Horizon
To run Horizon on your project, you need to add a separate [worker](/create-apps/app-reference/single-runtime-image#workers).
To do so, use the following configuration:
```yaml {configFile="app"}
applications:
myapp:
[...]
workers:
horizon:
commands:
start: |
php artisan horizon
```
To enable the worker, push your changes to Upsun:
```bash {location="Terminal"}
git add .
git commit -m "Enable Laravel Horizon"
upsun push
```
A new container is started automatically.
It will spawn the Horizon process after the next deploy.
## 3. Access your Horizon dashboard
If you have restricted access to Horizon in your `HorizonServiceProvider.php`,
log in to your app through the web.
Then, go to `/horizon` to access your Horizon dashboard.

## 4. Optional: Customize Horizon
Horizon handles jobs that are populated by the queue.
If you need to customize how Horizon works (queues, processes, etc.),
see the official [Laravel Horizon documentation](https://laravel.com/docs/master/horizon#main-content).
Warning
Web and worker containers don’t share mount targets.
You can’t share files between those containers using the filesystem.
To share data between containers, use services.
Note that you can customize the resources of your Horizon worker container from the Upsun Console.

For more information, see how to [configure resources](/manage-resources/adjust-resources.md).
# Add services [ClickHouse](https://docs.upsun.com/add-services/clickhouse.html)
ClickHouse is a high-performance column-oriented, distributed, OLAP (Online Analytical Processing) database.
It allows you to generate real-time analytical data reports using SQL queries.
For more information, see the [ClickHouse documentation](https://ClickHouse.com/docs).
Note
Upsun supports ClickHouse with the following limitations:
High availability of service isn’t supported.
You can only configure single-node ClickHouse clusters.
## Supported versions
- 24.3
- 23.8
Upsun plans on supporting long-term support ClickHouse versions in priority.
## Relationship reference
For each service [defined via a relationship](#usage-example) to your application,
Upsun automatically generates corresponding environment variables within your application container,
in the ``$_`` format.
Here is example information available through the [service environment variables](/development/variables/_index.md#service-environment-variables) themselves,
or through the [``PLATFORM_RELATIONSHIPS`` environment variable](/development/variables/use-variables.md#use-provided-variables).
You can obtain the complete list of available service environment variables in your app container by running upsun ssh env.
Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the service environment variables directly rather than hard coding any values.
For some advanced use cases, you can use the PLATFORM_RELATIONSHIPS environment variable.
The structure of the PLATFORM_RELATIONSHIPS environment variable can be obtained by running upsun relationships in your terminal:
# Decode the built-in credentials object variable.exportRELATIONSHIPS_JSON=$(echo$PLATFORM_RELATIONSHIPS| base64 --decode)# Set environment variables for individual credentials.exportAPP_CLICKHOUSE_HOST=="$(echo$RELATIONSHIPS_JSON| jq -r '.clickhouse[0].host')"
## Usage example
### 1. Configure the service
To define the service, use the `clickhouse` type:
```yaml {configFile="app"}
services:
# The name of the service container. Must be unique within a project.
:
type: clickhouse:
```
Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service.
### 2. Define the relationship
To define the relationship, use one of the following endpoints.
#### `clickhouse` endpoint
The `clickhouse` endpoint allows you to use the Native Protocol port (also known as ClickHouse TCP protocol).
This protocol is used by ClickHouse apps and processes such as `clickhouse-server`, `clickhouse-client`, and native ClickHouse tools. It is also used for inter-server communication for distributed queries.
Use the following configuration:
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<SERVICE_NAME>:
You can define <SERVICE_NAME> as you like.
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<RELATIONSHIP_NAME>:service:<SERVICE_NAME>endpoint:clickhouse
You can define <SERVICE_NAME> and <RELATIONSHIP_NAME> as you like, but it’s best if they’re distinct.
With this definition, the application container (<APP_NAME>) now has access to the service via the corresponding service environment variables.
#### `clickhouse-http` endpoint
The `clickhouse-http` endpoint allows you to use the HTTP API Port for HTTP requests.
This protocol is used by [JDBC](https://docs.oracle.com/javase/8/docs/technotes/guides/jdbc/), [ODBC](https://learn.microsoft.com/en-us/sql/odbc/microsoft-open-database-connectivity-odbc?view=sql-server-ver16), and web interfaces.
Use the following configuration:
```yaml {configFile="app"}
applications:
# The name of the app container. Must be unique within a project.
:
# Relationships enable access from this app to a given service.
# The example below shows configuration with an explicitly set service name and endpoint.
# See the Application reference for all options for defining relationships and endpoints.
relationships:
:
service:
endpoint: clickhouse-http
services:
# The name of the service container. Must be unique within a project.
:
type: clickhouse:
```
You can define ```` and ```` as you like, so long as it's unique between all defined services and relationships
and matches in both the application and services configuration.
With this definition, the application container (````) now has access to the service via the corresponding [service environment variables](/development/variables/_index.md#service-environment-variables).
### Example configuration
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:clickhouse:services:# The name of the service container. Must be unique within a project.clickhouse:type:clickhouse:24
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:clickhouse:service:clickhouseendpoint:clickhouseservices:# The name of the service container. Must be unique within a project.clickhouse:type:clickhouse:24.3
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:clickhouse:service:clickhouseendpoint:clickhouse-httpservices:# The name of the service container. Must be unique within a project.clickhouse:type:clickhouse:24.3
If you want to change the clickhouse endpoint to clickhouse-http, you need to use explicit endpoint definition as it defaults to clickhouse endpoint when using default endpoint (aka. SERVICE_NAME as relationship definition).
## Multiple databases
You can configure multiple databases, much like [with PostgreSQL](/add-services/postgresql.md#multiple-databases).
To do so, you can use a configuration similar to the following:
```yaml {configFile="app"}
# Complete list of all available properties: https://docs.upsun.com/create-apps/app-reference.html
applications:
myapp:
# Relationships enable access from this app to a given service.
# The example below shows configuration with explicitly set service names and endpoints.
# See the Application reference for all options for defining relationships and endpoints.
relationships:
clickhouse-admin:
service: clickhouse
endpoint: admin
clickhouse-reporter:
service: clickhouse
endpoint: reporter
clickhouse-importer:
service: clickhouse
endpoint: importer
services:
clickhouse:
type: clickhouse:24.3
configuration:
databases:
- main
- legacy
endpoints:
admin:
port: 9000 # binary port
privileges:
main: admin
legacy: admin
reporter:
default_database: main
port: 8123 # http port
privileges:
main: ro
importer:
default_database: legacy
port: 9000 # binary port
privileges:
legacy: rw
```
# Deploy Symfony on Upsun [Configure workers](https://docs.upsun.com/get-started/stacks/symfony/workers.html)
Workers (or consumers) are a great way to off-load processing in the background
to make an app as fast as possible.
You can implement workers in Symfony smoothly thanks to the [Messenger component](https://symfony.com/doc/current/components/messenger.html).
To deploy a worker, add an entry under the `workers` section [in your app configuration](/create-apps/_index.md):
```yaml {configFile="app"}
applications:
myapp:
workers:
mails:
commands:
start: symfony console messenger:consume --time-limit=60 --memory-limit=128M
```
Note that the `symfony` binary is available when you use the [Symfony
integration](./integration) in your Upsun app configuration.
On Upsun, worker containers run the exact same code as the web container.
The container image is built only once and deployed multiple times in its own container alongside the web container.
The *build* hook and dependencies might not vary but,
as these containers are independent, they can be customized the same way using common properties.
The values defined for the main container are used as default values.
Tip
When the container is running in the context of a worker, the
SYMFONY_IS_WORKER environment variable is defined and set to 1.
The `commands.start` key is required.
It specifies the command you can use to launch the application worker.
If the command specified by the `start` key terminates, it's restarted automatically.
For more information, see [Workers](/create-apps/app-reference/single-runtime-image#workers).
Warning
Web and worker containers don’t share mounts targets.
So you can’t share files between those containers using the filesystem.
To share data between containers, use services.
# Deploy Laravel on Upsun [Set up cron jobs](https://docs.upsun.com/get-started/stacks/laravel/crons.html)
Cron jobs allow you to run scheduled tasks at specified times or intervals.
While you can run your own custom tasks, Laravel provides a scheduler to simplify the implementation.
To implement it, see the Laravel [Task Scheduling documentation](https://laravel.com/docs/master/scheduling).
## Set up a cron job
To set up a cron job, update your Upsun configuration as follows:
```yaml {configFile="app"}
applications:
myapp:
[...]
crons:
snapshot:
spec: * * * * *
commands:
start: |
php artisan schedule:run >> /dev/null 2>&1
```
## Run cron jobs based on environment type
To run a command in a cron hook for specific environment types,
use the `PLATFORM_ENVIRONMENT_TYPE` environment variable:
```yaml {configFile="app"}
applications:
myapp:
[...]
crons:
snapshot:
spec: 0 5 * * *
commands:
start: |
# only run for the production environment, aka main branch
if [ "$PLATFORM_ENVIRONMENT_TYPE" = "production" ]; then
php artisan schedule:run >> /dev/null 2>&1
fi
```
## Run the Laravel scheduler every minute
Cron job execution on the default Upsun offering are limited to once every 5 minutes.
For more information, see the [documentation on crons](/create-apps/app-reference/single-runtime-image#crons).
However, you can add a [worker](/create-apps/app-reference/single-runtime-image#workers)
and specify a start command that [runs the scheduler every minute](https://laravel.com/docs/11.x/scheduling#running-the-scheduler-locally).
To do so, use the following configuration:
```yaml {configFile="app"}
applications:
APP_NAME:
[...]
workers:
scheduler:
commands:
start: |
php artisan schedule:work
```
Warning
Web and worker containers don’t share mount targets.
You can’t share files between those containers using the filesystem.
To share data between containers, use services.
# Deploy Symfony on Upsun [Set up cron jobs](https://docs.upsun.com/get-started/stacks/symfony/crons.html)
Cron jobs allow you to run scheduled tasks at specified times or intervals.
To set up a cron job, add a configuration similar to the following:
```yaml {configFile="app"}
applications:
myapp:
crons:
snapshot:
spec: 0 5 * * *
commands:
start: |
croncape symfony ...
```
To run a command in a cron hook for specific environment types,
use the `PLATFORM_ENVIRONMENT_TYPE` environment variable:
```yaml {configFile="app"}
applications:
myapp:
crons:
snapshot:
spec: 0 5 * * *
commands:
start: |
# only run for the production environment, aka main branch
if [ "$PLATFORM_ENVIRONMENT_TYPE" = "production" ]; then
croncape symfony ...
fi
```
## Use croncape
When using the [Symfony integration](./integration),
you can use `croncape` to get feedback through emails when something goes wrong.
To specify which email address `croncape` must send the feedback emails to,
add a `MAILTO` environment variable.
To do so, run the following command:
```bash
symfony var:create -y --level=project --name=env:MAILTO --value=sysadmin@example.com
```
To ensure better reliability, `croncape` sends the emails using:
- `project-id@cron.noreply.platformsh.site` as the sender address (`project-id+branch@cron.noreply.platformsh.site` for non-main environments)
- the provided [UpsunSMTP service](./environment-variables#emails), even if you define your own `MAILER_*` environment variables
To use a custom SMTP and/or custom sender address, follow these steps:
1. To specify a sender address, define a [`MAILFROM` environment variable](./environment-variables.md#symfony-environment-variables).
2. Define the mandatory [environment variables to use your own email service](./environment-variables#emails).
Note that only SMTP connections are supported.
3. To disable the provided SMTP service, run `symfony upsun:env:info enable_smtp false`.
Note
To use croncape, SMTP must be enabled on the environment, where the PLATFORM_SMTP_HOST environment variable is accessible.
This variable is available, and SMTP enabled, by default on all production environments.
This is not the case for preview (non-production) environments, where it must be enabled with the command symfony cloud:env:info enable_smtp true.
# Add services [Elasticsearch (Search service)](https://docs.upsun.com/add-services/elasticsearch.html)
Elasticsearch is a distributed RESTful search engine built for the cloud.
See the [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html) for more information.
## Supported versions
You can select the major and minor version.
Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches.
8.5
7.17
## Deprecated versions
The following versions are still available in your projects for free,
but they're at their end of life and are no longer receiving security updates from upstream.
7.10
7.9
7.7
7.5
7.2
6.8
6.5
5.4
5.2
2.4
1.7
1.4
To ensure your project remains stable in the future,
switch to [a premium version](#supported-versions).
Alternatively, you can switch to one of the latest, free versions of [OpenSearch](./opensearch.md).
To do so, follow the same procedure as for [upgrading](#upgrading).
## Relationship reference
For each service [defined via a relationship](#usage-example) to your application,
Upsun automatically generates corresponding environment variables within your application container,
in the ``$_`` format.
Here is example information available through the [service environment variables](/development/variables/_index.md#service-environment-variables) themselves,
or through the [``PLATFORM_RELATIONSHIPS`` environment variable](/development/variables/use-variables.md#use-provided-variables).
You can obtain the complete list of available service environment variables in your app container by running upsun ssh env.
Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the service environment variables directly rather than hard coding any values.
For some advanced use cases, you can use the PLATFORM_RELATIONSHIPS environment variable.
The structure of the PLATFORM_RELATIONSHIPS environment variable can be obtained by running upsun relationships in your terminal:
# Decode the built-in credentials object variable.exportRELATIONSHIPS_JSON=$(echo$PLATFORM_RELATIONSHIPS| base64 --decode)# Set environment variables for individual credentials.exportAPP_ELASTICSEARCH_HOST=="$(echo$RELATIONSHIPS_JSON| jq -r '.elasticsearch[0].host')"
For [premium versions](#supported-versions),
the service type is `elasticsearch-enterprise`.
## Usage example
### 1. Configure the service
To define the service, use the `elasticsearch` type:
```yaml {configFile="app"}
services:
# The name of the service container. Must be unique within a project.
:
type: elasticsearch:
```
If you’re using a [premium version](/add-services/elasticsearch.md#supported-versions), use the ``elasticsearch-enterprise`` type instead.
Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service.
### 2. Define the relationship
To define the relationship, use the following configuration:
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<SERVICE_NAME>:
You can define <SERVICE_NAME> as you like, so long as it’s unique between all defined services
and matches in both the application and services configuration.
The example above leverages default endpoint configuration for relationships.
That is, it uses default endpoints behind-the-scenes, providing a relationship
(the network address a service is accessible from) that is identical to the name of that service.
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<RELATIONSHIP_NAME>:service:<SERVICE_NAME>endpoint:elasticsearch
You can define <SERVICE_NAME> and <RELATIONSHIP_NAME> as you like, so long as it’s unique between all defined services and relationships
and matches in both the application and services configuration.
The example above leverages explicit endpoint configuration for relationships.
applications:# The name of the app container. Must be unique within a project.myapp:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:elasticsearch:services:# The name of the service container. Must be unique within a project.elasticsearch:type:elasticsearch:8.5
If you’re using a premium version, use the elasticsearch-enterprise type instead.
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:elasticsearch:service:elasticsearchendpoint:elasticsearchservices:# The name of the service container. Must be unique within a project.elasticsearch:type:elasticsearch:8.5
If you’re using a premium version, use the elasticsearch-enterprise type instead.
### Use in app
To use the configured service in your app, add a configuration file similar to the following to your project.
Note that configuration for [premium versions](#supported-versions) may differ slightly.
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:elasticsearch:services:elasticsearch:type:elasticsearch:8.5
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/myapp"# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:elasticsearch:service:elasticsearchendpoint:elasticsearchservices:elasticsearch:type:elasticsearch:8.5
This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory.
`myapp` has access to the `elasticsearch` service, via the corresponding [service environment variables](/development/variables/_index.md#service-environment-variables)
(as per [default endpoint](/create-apps/app-reference/single-runtime-image#relationships) configuration for relationships).
From this, `myapp` can retrieve access credentials to the service through the [relationship environment variable](/add-services/elasticsearch.md#relationship-reference).
```bash {location="myapp/.environment"}
# Set environment variables for individual credentials,
# For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables.
export ELASTIC_SCHEME=${ELASTICSEARCH_SCHEME}
export ELASTIC_HOST=${ELASTICSEARCH_HOST}
export ELASTIC_PORT=${ELASTICSEARCH_PORT}
# Surface more common Elasticsearch connection string variables for use in app.
export ELASTIC_USERNAME=${ELASTICSEARCH_USERNAME}
export ELASTIC_PASSWORD=${ELASTICSEARCH_PASSWORD}
export ELASTIC_HOSTS=["$ELASTIC_SCHEME://$ELASTIC_HOST:$ELASTIC_PORT"]
```
The above file — ``.environment`` in the ``myapp`` directory — is automatically sourced by Upsun into the runtime environment, so that the variable ``ELASTIC_HOSTS`` can be used within the application to connect to the service.
Note that ``ELASTIC_HOSTS``, and all [Upsun-service environment variables](/development/variables/_index.md#service-environment-variables) like ``ELASTICSEARCH_HOST``,
are environment-dependent.
Unlike the build produced for a given commit,
they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment.
A file very similar to this is generated automatically for your when using the ``upsun ify`` command to [migrate a codebase to Upsun](/get-started/_index.md).
Note
When you create an index on Elasticsearch,
don’t specify the number_of_shards or number_of_replicas settings in your Elasticsearch API call.
These values are set automatically based on available resources.
## Authentication
By default, Elasticsearch has no authentication.
No username or password is required to connect to it.
Starting with Elasticsearch 7.2 you may optionally enable HTTP Basic authentication.
To do so, include the following in your `.upsun/config.yaml` configuration:
```yaml {configFile="services"}
services:
# The name of the service container. Must be unique within a project.
elasticsearch:
type: elasticsearch:8.5
configuration:
authentication:
enabled: true
```
If you're using a [premium version](#supported-versions),
use the `elasticsearch-enterprise` type.
That enables mandatory HTTP Basic auth on all requests.
The credentials are available in any relationships that point at that service,
in the `username` and `password` properties.
You can obtain the complete list of available service environment variables in your app container by running ``upsun ssh env``.
Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the [service environment variables](/development/variables/_index.md#service-environment-variables) directly rather than hard coding any values.
This functionality is generally not required if Elasticsearch isn't exposed on its own public HTTP route.
However, certain applications may require it, or it allows you to safely expose Elasticsearch directly to the web.
To do so, add a route to `.upsun/config.yaml` that has `elasticsearch:elasticsearch` as its upstream
(where `elasticsearch` is whatever you named the service).
For example:
```yaml {configFile="routes"}
routes:
"https://es.{default}/":
type: upstream
upstream: "elasticsearch:elasticsearch"
services:
# The name of the service container. Must be unique within a project.
elasticsearch:
type: elasticsearch:8.5
configuration:
authentication:
enabled: true
```
## Plugins
Elasticsearch offers a number of plugins.
To enable them, list them under the `configuration.plugins` key in your `.upsun/config.yaml` file, like so:
```yaml {configFile="services"}
services:
# The name of the service container. Must be unique within a project.
elasticsearch:
type: elasticsearch:8.5
configuration:
plugins:
- analysis-icu
```
If you're using a [premium version](#supported-versions),
use the `elasticsearch-enterprise` type.
In this example you'd have the ICU analysis plugin and Python script support plugin.
If there is a publicly available plugin you need that isn't listed here, [contact support](/learn/overview/get-support.md).
### Available plugins
This is the complete list of official Elasticsearch plugins that can be enabled:
| Plugin | Description | 2.4 | 5.x | 6.x | 7.x | 8.x |
|-------------------------|-------------------------------------------------------------------------------------------|-----|-----|-----|-----|-----|
| `analysis-icu` | Support ICU Unicode text analysis | * | * | * | * | * |
| `analysis-nori` | Integrates Lucene Nori analysis module into Elasticsearch | | | * | * | * |
| `analysis-kuromoji` | Japanese language support | * | * | * | * | * |
| `analysis-smartcn` | Smart Chinese Analysis Plugins | * | * | * | * | * |
| `analysis-stempel` | Stempel Polish Analysis Plugin | * | * | * | * | * |
| `analysis-phonetic` | Phonetic analysis | * | * | * | * | * |
| `analysis-ukrainian` | Ukrainian language support | | * | * | * | * |
| `cloud-aws` | AWS Cloud plugin, allows storing indices on AWS S3 | * | | | | |
| `delete-by-query` | Support for deleting documents matching a given query | * | | | | |
| `discovery-multicast` | Ability to form a cluster using TCP/IP multicast messages | * | | | | |
| `ingest-attachment` | Extract file attachments in common formats (such as PPT, XLS, and PDF) | | * | * | * | * |
| `ingest-user-agent` | Extracts details from the user agent string a browser sends with its web requests | | * | * | | |
| `lang-javascript` | JavaScript language plugin, allows the use of JavaScript in Elasticsearch scripts | | * | | | |
| `lang-python` | Python language plugin, allows the use of Python in Elasticsearch scripts | * | * | | | |
| `mapper-annotated-text` | Adds support for text fields with markup used to inject annotation tokens into the index | | | * | * | * |
| `mapper-attachments` | Mapper attachments plugin for indexing common file types | * | * | | | |
| `mapper-murmur3` | Murmur3 mapper plugin for computing hashes at index-time | * | * | * | * | * |
| `mapper-size` | Size mapper plugin, enables the `_size` meta field | * | * | * | * | * |
| `repository-s3` | Support for using S3 as a repository for Snapshot/Restore | | * | * | * | * |
| `transport-nio` | Support for NIO transport | | | | * | * |
### Plugin removal
Removing plugins previously added in your `.upsun/config.yaml` file doesn't automatically uninstall them from your Elasticsearch instances.
This is deliberate, as removing a plugin may result in data loss or corruption of existing data that relied on that plugin.
Removing a plugin usually requires reindexing.
To permanently remove a previously enabled plugin,
[upgrade the service](#upgrading) to create a new instance of Elasticsearch and migrate to it.
In most cases it isn't necessary as an unused plugin has no appreciable impact on the server.
## Upgrading
The Elasticsearch data format sometimes changes between versions in incompatible ways.
Elasticsearch doesn't include a data upgrade mechanism as it's expected that all indexes can be regenerated from stable data if needed.
To upgrade (or downgrade) Elasticsearch, use a new service from scratch.
There are two ways to do so.
### Destructive
In your `.upsun/config.yaml` file, change the version *and* name of your Elasticsearch service.
Be sure to also update the reference to the now changed service name in its corresponding application's `relationship` block.
When you push that to Upsun, the old service is deleted and a new one with the new name is created with no data.
You can then have your application reindex data as appropriate.
This approach has the downsides of temporarily having an empty Elasticsearch instance,
which your application may or may not handle gracefully, and needing to rebuild your index afterward.
Depending on the size of your data that could take a while.
### Transitional
With a transitional approach, you temporarily have two Elasticsearch services.
Add a second Elasticsearch service with the new version, a new name, and give it a new relationship in `.upsun/config.yaml`.
You can optionally run in that configuration for a while to allow your application to populate indexes in the new service as well.
Once you're ready to switch over, remove the old Elasticsearch service and relationship.
You may optionally have the new Elasticsearch service use the old relationship name if that's easier for your app to handle.
Your application is now using the new Elasticsearch service.
This approach has the benefit of never being without a working Elasticsearch instance.
On the downside, it requires two running Elasticsearch servers temporarily,
each of which consumes resources and needs adequate disk space.
Depending on the size of your data, that may be a lot of disk space.
# Python [Manage Python dependencies](https://docs.upsun.com/languages/python/dependencies.html)
Note
You can now use composable image (BETA) to install runtimes and tools in your application container. To find out more, see the dedicated documentation page.
You can manage Python packages in different ways.
Python images come with pip installed,
but they're flexible enough so you can choose what package manager you want.
This article describes how to configure major package management tools.
This package management is different from global dependencies (packages available as commands),
which you can add in your [app configuration](../../create-apps/_index.md).
See more about [managing global dependencies](./_index.md#package-management).
## Pip
[pip](https://pip.pypa.io/en/stable/) is the primary package installer for Python
and comes installed on every Python container.
You can use it to install packages from the Python Package Index and other locations.
To manage packages with pip,
commit a `requirements.txt` file with all of the dependencies needed for your app.
Then install the packages in your [`build` hook](../../create-apps/hooks/_index.md),
such as by running the following command: `pip install -r requirements.txt`.
The following sections present ideas to keep in mind to ensure repeatable deployments on Upsun.
### pip version
The version of pip on Python containers gets updated regularly.
But it isn't guaranteed to be the latest version or the version that matches your local environment.
You might want to define a specific version of pip in your deployments to further enforce repeatable builds.
To do so, modify your [app configuration](../../create-apps/_index.md), as in the following examples:
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"type:'python:3.9'hooks:build:| # Fail the build if any errors occur
set -eu
# Download the latest version of pip
python3.9 -m pip install --upgrade pip
# Install dependencies
pip install -r requirements.txt
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"type:'python:3.9'variables:env:PIP_VERSION:'22.3.1'hooks:build:| # Fail the build if any errors occur
set -eu
# Download a specific version of pip
python3.9 -m pip install pip==$PIP_VERSION
# Install dependencies
pip install -r requirements.txt
### pip freeze
You can write `requirements.txt` files in various ways.
You can specify anything from the latest major to a specific patch version in a [requirement specifier](https://pip.pypa.io/en/stable/reference/requirement-specifiers/).
Use `pip freeze` before committing your requirements to pin specific package versions.
This ensures repeatable builds on Upsun with the same packages.
## Pipenv
[Pipenv](https://pipenv.pypa.io/en/latest/) is a package manager for Python
that creates and manages a virtual environment for Python projects.
Dependencies are tracked and defined within a `Pipfile`.
It also generates a `Pipfile.lock` file to produce repeatable installs.
You can specify the latest or a specific version of Pipenv
in your deployments to ensure repeatable builds.
Because Pipenv depends on pip, you might want to also specify the pip version.
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"type:'python:3.9'dependencies:python3:pipenv:'*'hooks:build:| # Fail the build if any errors occur
set -eu
# Download the latest version of pip
python3.9 -m pip install --upgrade pip
# Install dependencies
# Include `--deploy` to fail the build if `Pipfile.lock` isn't up to date
pipenv install --deploy
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"type:'python:3.9'variables:env:PIP_VERSION:'22.3.1'dependencies:python3:pipenv:'2022.12.19'hooks:build:| # Fail the build if any errors occur
set -eu
# Download a specific version of pip
python3.9 -m pip install pip==$PIP_VERSION
# Install dependencies
# Include `--deploy` to fail the build if `Pipfile.lock` isn't up to date
pipenv install --deploy
## Poetry
[Poetry](https://python-poetry.org/docs/) is a tool for dependency management and packaging in Python.
It allows you to declare the libraries your project depends on and manages them for you.
Poetry offers a lock file to ensure repeatable installs and can build your project for distribution.
It also creates and manages virtual environments to keep project work isolated from the rest of your system.
To set up Poetry on Upsun, follow these steps:
1. Configure your virtual environment by setting two variables in your [app configuration](../../create-apps/_index.md).
- [`POETRY_VIRTUALENVS_IN_PROJECT`](https://python-poetry.org/docs/configuration/#virtualenvsin-project):
Setting this to `true` places the virtual environment at the root of the app container: `/app/.venv`.
- [`POETRY_VIRTUALENVS_CREATE`](https://python-poetry.org/docs/configuration/#virtualenvscreate):
Setting this to `true` ensures that the same virtual environment created during the build hook is reused in subsequent steps.
Set the variables as follows:
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
myapp:
type: 'python:3.9'
variables:
env:
POETRY_VIRTUALENVS_IN_PROJECT: true
POETRY_VIRTUALENVS_CREATE: true
```
2. Install Poetry.
You can specify the latest or a specific version of Poetry in your deployments to ensure repeatable builds.
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"type:'python:3.9'dependencies:python3:poetry:'*'variables:env:POETRY_VIRTUALENVS_IN_PROJECT:truePOETRY_VIRTUALENVS_CREATE:truehooks:build:| # Fail the build if any errors occur
set -eu
# Download the latest version of pip
python3.9 -m pip install --upgrade pip
# Install dependencies
poetry install
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"type:'python:3.9'dependencies:python3:poetry:'>=1.8'variables:env:POETRY_VIRTUALENVS_IN_PROJECT:truePOETRY_VIRTUALENVS_CREATE:truehooks:build:| # Fail the build if any errors occur
set -eu
# Download the latest version of pip
python3.9 -m pip install --upgrade pip
# Install dependencies
poetry install
3. Make Poetry available outside the build hook.
Although step 2 updated the `PATH` to make Poetry available during the build hook,
it isn't enough to make it available at subsequent stages.
To use Poetry in a start command, a deploy hook, or during SSH sessions,
update the `PATH` in a [`.environment` file](../../development/variables/set-variables.md#set-variables-via-script).
```text {location=".environment"}
# Updates PATH when Poetry is used, making it available during deploys, start commands, and SSH.
if [ -n "$POETRY_VERSION" ]; then
export PATH="/app/.local/bin:$PATH"
fi
```
# Frameworks [Deploy Next.js on {{% vendor/name %}}](https://docs.upsun.com/get-started/stacks/nextjs.html)
Note
Before you start, check out the Upsun demo app and the main Getting started guide.
They provide all of the core concepts and common commands you need to know before using the materials below.
## Before you begin
You need:
- [Git](https://git-scm.com/downloads).
Git is the primary tool to manage everything your app needs to run.
Push commits to deploy changes and control configuration through YAML files.
These files describe your infrastructure, making it transparent and version-controlled.
- A Upsun account.
If you don't already have one, [register for a trial account](https://auth.upsun.com/register).
You can sign up with an email address or an existing GitHub, Bitbucket, or Google account.
If you choose one of these accounts, you can set a password for your Upsun account later.
- The [Upsun CLI](/administration/cli/_index.md).
This lets you interact with your project from the command line.
You can also do most things through the [Web Console](/administration/web/_index.md).
## 1. Create a Next.js app
To create your Next.js app, follow these steps.
1. Follow the Next.js [installation guide](https://nextjs.org/docs/getting-started/installation).
To fast track the process, run the following commands:
```bash {location="Terminal"}
npx create-next-app@latest myapp
```
2. To initialize the local Git repository and commit local files, run the following commands:
```bash {location="Terminal"}
cd myapp
git init
git add .
git commit -m "Init Next.js application."
```
Note
You can view the running app locally by running npm run dev.
## 2. Create a new project
To create a project on Upsun,
follow these steps.
Remember
After creating your Upsun project, copy your new project ID for later use.
To create a new project with the Upsun CLI, use the following command and follow the prompts:
Terminal
upsun project:create
Note
When creating a new project using the Upsun CLI command project:create,
you are asked if you want to set the local remote to your new project. Enter Yes (y).
Your local source code is automatically linked to your newly created Upsun project
through the creation of a .upsun/local/project.yaml.
This file contains the corresponding <projectId> for the Upsun CLI to use,
and sets a Git remote to upsun.
You can define resources for your project later on, after your first push.
To link your local source code to your new Upsun project,
run the following command:
Terminal
upsun project:set-remote <projectId>
This command adds a new remote called upsun to your local Git repository,
which is equivalent to the following commands:
Terminal
git remote
origin
upsun
It also creates a new .upsun/local/project.yaml file that contains the <projectId>
for the upsun CLI to use.
Tip
If you forget your <projectId>, run the following command and find your project in the list:
Terminal
upsun project:list
## 3. Choose your Git workflow
You can use Upsun projects as a classic Git repository,
where you are able to push your source code in different ways,
using either the Git CLI or the Upsun CLI.
You can choose which way —or Git workflow— you want to use for your project from the following options:
- Your project source code is **hosted on a Upsun Git repository**
- Your project source code is **hosted on your own GitHub repository**
For the rest of this guide, you will use the normal Git workflow (git add . && git commit -m "message" && git push upsun) to commit your source code changes to Git history.
You will also use the Upsun CLI to deploy your Upsun environment with the latest code updates.
Upsun provides a Github integration that allows your Upsun project to be fully integrated with your Github repository.
This enables you, as a developer, to use a normal Git workflow (git add . && git commit -m "message" && git push) to deploy your environment—with no need to connect to the Upsun Console.
Note
Make sure you complete the following steps before adding a Github integration:
## 4. Configure your project
To host your Next.js application on Upsun,
you need to have a few YAML configuration files at the root of your project.
These files manage your app's behavior.
They are located in a `.upsun/` folder at the root of your source code
and structured in a similar way to this:
```txt
myapp
├── .upsun
│ └── config.yaml
├── [.environment]
└──
```
To generate these files, run the following command at the root of your project:
``` {location="Terminal"}
upsun project:init
```
Follow the prompts, and you should result in such a config file.
```yaml {configFile="apps"}
applications:
myapp:
source:
root: "/"
type: "nodejs:22"
mounts:
"/.npm":
source: "storage"
source_path: "npm"
hooks:
build: |
set -eux
npm i
npm run build
web:
commands:
start: npm run start -p $PORT
locations:
"/":
passthru: true
routes:
"https://{default}/": { type: upstream, upstream: "myapp:http" }
"http://{default}/": { type: redirect, to: "https://{default}/" }
```
As an example, above is the minimum configuration needed to deploy a Next.js application on Upsun without any services.
Depending on your answers to the prompts, you may also have `relationships` and `services` defined.
To commit your new files, run the following commands:
```bash {location="Terminal"}
git add .
git commit -m "Add Upsun config files"
```
## 5. Deploy
And just like that, it’s time to deploy!
Depending on the Git workflow you chose at the beginning of this tutorial,
there are two ways to deploy your source code changes.
You can push your code using the normal Git workflow (git add . && git commit -m "message" && git push).
This pushes your source code changes to your upsun remote repository.
Alternatively, you can use the following Upsun CLI command:
Terminal
upsun push
When you choose to use a third-party Git hosting service, the Upsun Git
repository becomes a read-only mirror of the third-party repository. All your
changes take place in the third-party repository.
Add an integration to your existing third-party repository:
If you are using an integration, on each code updates,
use the normal Git workflow (git add . && git commit -m "message" && git push) to push your code to your external repository.
To do so, run the following command:
Terminal
git push origin
Your GitHub, GitLab, or Bibucket integration process then automatically deploys changes to your environment.
If you’re pushing a new Git branch, a new environment is created.
Upsun then reads your configuration files,
and deploys your project using [default container resources](/manage-resources/resource-init.md).
If you don't want to use those default resources,
define your own [resource initialization strategy](/manage-resources/resource-init#specify-a-resource-initialization-strategy),
or [amend those default container resources](/manage-resources/adjust-resources.md) after your project is deployed.
Et voilà, your Next.js application is live!
Tip
Each environment has its own domain name.
To open the URL of your new environment, run the following command:
Terminal
upsun environment:url --primary
## 6. Make changes to your project
Now that your project is deployed, you can start making changes to it.
For example, you might want to fix a bug or add a new feature.
In your project, the `main` branch always represents the production environment.
Other branches are for developing new features, fixing bugs, or updating the infrastructure.
To make changes to your project, follow these steps:
1. Create a new environment (a Git branch) to make changes without impacting production:
```bash {location="Terminal"}
upsun branch feat-a
```
This command creates a new local `feat-a` Git branch based on the main Git branch,
and activates a related environment on Upsun.
The new environment inherits the data (service data and assets) of its parent environment (the production environment here).
2. Make changes to your project.
For example, edit the `views/index.jade` file and make the following changes:
```diff
diff --git a/views/index.jade b/views/index.jade
index 3d63b9a..77aee43 100644
--- a/views/index.jade
+++ b/views/index.jade
@@ -2,4 +2,4 @@ extends layout
block content
h1= title
- p Welcome to #{title}
+ p Welcome to #{title} on Upsun
``
3. Commit your changes:
```bash {location="Terminal"}
git add views/index.jade
git commit -m "Update index page view."
```
4. Deploy your changes to the `feat-a` environment:
```bash {location="Terminal"}
upsun push
```
5. Iterate by changing the code, committing, and deploying.
When satisfied with your changes, merge them to the main branch,
and remove the feature branch:
```bash {location="Terminal"}
upsun merge
Are you sure you want to merge feat-a into its parent, main? [Y/n] y
upsun checkout main
git pull upsun main
upsun environment:delete feat-a
git fetch --prune
```
Note that deploying to production is fast because the image built for the `feat-a` environment is reused.
For a long running branch, to keep the code up-to-date with the main branch, use `git merge main` or `git rebase main`.
You can also keep the data in sync with the production environment by using `upsun env:sync`.
## Further resources
### Documentation
- [JavaScript/Node.js documentation](/languages/nodejs/)
- [Managing dependencies](/languages/nodejs#dependencies)
### Community content
- [Next.js topics](https://support.platform.sh/hc/en-us/search?utf8=%E2%9C%93&query=nextjs)
- [Node.js topics](https://support.platform.sh/hc/en-us/search?utf8=%E2%9C%93&query=node)
- [JavaScript topics](https://support.platform.sh/hc/en-us/search?utf8=%E2%9C%93&query=js)
### Blogs
- [A quick-start guide on hosting Next.js on Upsun](https://upsun.com/blog/setting-up-next-js-on-upsun/)
# Add services [Gotenberg](https://docs.upsun.com/add-services/gotenberg.html)
Gotenberg is a stateless API for converting various document formats into PDF files.
For more information, see the [Gotenberg documentation](https://gotenberg.dev/docs/getting-started/introduction).
## Supported versions
- 8
You can select the major version. But the latest compatible minor version is applied automatically and can’t be overridden.
Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches.
## Relationship reference
For each service [defined via a relationship](#usage-example) to your application,
Upsun automatically generates corresponding environment variables within your application container,
in the ``$_`` format.
Here is example information available through the [service environment variables](/development/variables/_index.md#service-environment-variables) themselves,
or through the [``PLATFORM_RELATIONSHIPS`` environment variable](/development/variables/use-variables.md#use-provided-variables).
You can obtain the complete list of available service environment variables in your app container by running upsun ssh env.
Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the service environment variables directly rather than hard coding any values.
For some advanced use cases, you can use the PLATFORM_RELATIONSHIPS environment variable.
The structure of the PLATFORM_RELATIONSHIPS environment variable can be obtained by running upsun relationships in your terminal:
# Decode the built-in credentials object variable.exportRELATIONSHIPS_JSON=$(echo$PLATFORM_RELATIONSHIPS| base64 --decode)# Set environment variables for individual credentials.exportAPP_GOTENBERG_HOST=="$(echo$RELATIONSHIPS_JSON| jq -r '.gotenberg[0].host')"
## Usage example
### 1. Configure the service
To define the service, use the `gotenberg` type:
```yaml {configFile="app"}
services:
# The name of the service container. Must be unique within a project.
:
type: gotenberg:
```
Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service.
### 2. Define the relationship
To define the relationship, use the ``http`` endpoint:
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<SERVICE_NAME>:
You can define <SERVICE_NAME> as you like, so long as it’s unique between all defined services and matches in both the application and services configuration.
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<RELATIONSHIP_NAME>:service:<SERVICE_NAME>endpoint:http
You can define <SERVICE_NAME> and <RELATIONSHIP_NAME> as you like, so long as it’s unique between all defined services and relationships
and matches in both the application and services configuration.
With the above definition, Upsun uses the `http` endpoint,
providing a [relationship](/create-apps/app-reference/single-runtime-image#relationships) (the network address a service is accessible from) that is identical to the _name_ of that service.
The `http` endpoint uses port `3000` by default.
### Example configuration
applications:# The name of the app container. Must be unique within a project.myapp:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:gotenberg:services:# The name of the service container. Must be unique within a project.gotenberg:type:gotenberg:8
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:gotenberg:service:gotenbergendpoint:httpservices:# The name of the service container. Must be unique within a project.gotenberg:type:gotenberg:8
## Generate a PDF using Gotenberg
As an example, to generate a PDF file of the Upsun website, run the following cURL command:
```bash {location="Terminal"}
curl \
--request POST http://yduimhaby523ase4lju3qhimre.gotenberg8.service._.eu-3.platformsh.site/forms/chromium/convert/url \
--form url=https://upsun.com \
--form landscape=true \
--form marginTop=1 \
--form marginBottom=1 \
-o my.pdf
```
# Add services [Headless Chrome](https://docs.upsun.com/add-services/headless-chrome.html)
Headless Chrome is a headless browser that can be configured on projects like any other service on Upsun.
You can interact with the `chrome-headless` service container using Puppeteer, a Node.js library that provides an API to control Chrome over the DevTools Protocol.
Puppeteer can be used to generate PDFs and screenshots of web pages, automate form submission, and test your project's UI. You can find out more information about using Puppeteer on [GitHub](https://github.com/GoogleChrome/puppeteer) or in their [documentation](https://pptr.dev/).
## Supported versions
You can select the major version. But the latest compatible minor version is applied automatically and can’t be overridden.
Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches.
120
113
95
91
86
84
83
81
80
73
## Relationship reference
For each service [defined via a relationship](#usage-example) to your application,
Upsun automatically generates corresponding environment variables within your application container,
in the ``$_`` format.
Here is example information available through the [service environment variables](/development/variables/_index.md#service-environment-variables) themselves,
or through the [``PLATFORM_RELATIONSHIPS`` environment variable](/development/variables/use-variables.md#use-provided-variables).
You can obtain the complete list of available service environment variables in your app container by running upsun ssh env.
Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the service environment variables directly rather than hard coding any values.
For some advanced use cases, you can use the PLATFORM_RELATIONSHIPS environment variable.
The structure of the PLATFORM_RELATIONSHIPS environment variable can be obtained by running upsun relationships in your terminal:
# Decode the built-in credentials object variable.exportRELATIONSHIPS_JSON=$(echo$PLATFORM_RELATIONSHIPS| base64 --decode)# Set environment variables for individual credentials.exportAPP_HEADLESSCHROME_HOST=="$(echo$RELATIONSHIPS_JSON| jq -r '.chrome-headless[0].host')"
## Requirements
Puppeteer requires at least Node.js version 6.4.0, while using the async and await examples below requires Node 7.6.0 or greater.
If your app container uses a language other than Node.js, upgrade the Node.js version before using Puppeteer.
See how to [manage your Node.js version](../languages/nodejs/node-version.md).
## Usage example
### 1. Configure the service
To define the service, use the `chrome-headless` type:
```yaml {configFile="app"}
services:
# The name of the service container. Must be unique within a project.
:
type: chrome-headless:
```
Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service.
### 2. Define the relationship
To define the relationship, use the following configuration:
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<SERVICE_NAME>:
You can define <SERVICE_NAME> as you like, so long as it’s unique between all defined services
and matches in both the application and services configuration.
The example above leverages default endpoint configuration for relationships.
That is, it uses default endpoints behind-the-scenes, providing a relationship
(the network address a service is accessible from) that is identical to the name of that service.
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<RELATIONSHIP_NAME>:service:<SERVICE_NAME>endpoint:http
You can define <SERVICE_NAME> and <RELATIONSHIP_NAME> as you like, so long as it’s unique between all defined services and relationships
and matches in both the application and services configuration.
The example above leverages explicit endpoint configuration for relationships.
applications:# The name of the app container. Must be unique within a project.myapp:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:chrome-headless:services:# The name of the service container. Must be unique within a project.chrome-headless:type:chrome-headless:120
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:chrome-headless:service:chrome-headlessendpoint:httpservices:# The name of the service container. Must be unique within a project.chrome-headless:type:chrome-headless:120
### Use in app
After configuration, include [Puppeteer](https://www.npmjs.com/package/puppeteer) as a dependency:
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"type:"nodejs:22"[...]# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:chrome-headless:services:# The name of the service container. Must be unique within a project.chrome-headless:type:chrome-headless:120
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"type:"nodejs:22"[...]# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:chrome-headless:service:chrome-headlessendpoint:httpservices:# The name of the service container. Must be unique within a project.chrome-headless:type:chrome-headless:120
This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory.
`myapp` has access to the `chrome-headless` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship)
(as per [default endpoint](/create-apps/app-reference/single-runtime-image#relationships) configuration for relationships).
From this, `myapp` can retrieve access credentials to the service through the [relationship environment variable](/add-services/elasticsearch.md#relationship-reference).
```bash {location="myapp/.environment"}
# Set environment variables for individual credentials,
# For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables.
export CHROME_IP=${CHROME_HEADLESS_IP}
export CHROME_PORT=${CHROME_HEADLESS_PORT}
# Combine into a single base URL to be used within app.
export CHROME_BASEURL="http://${CHROME_IP}:${CHROME_PORT}"
```
The above file — `.environment` in the `myapp` directory — is automatically sourced by Upsun into the runtime environment, so that the variable `CHROME_BASEURL` can be used within the application to connect to the service.
Note that `CHROME_BASEURL` and all Upsun [service environment variables](/development/variables.html#service-environment-variables) like `CHROME_HEADLESS_HOST`, are environment-dependent. Unlike the build produced for a given commit, they can't be reused across environments and only allow your app to connect to a single service instance on a single environment.
A file very similar to this is generated automatically for your when using the `upsun ify` command to [migrate a codebase to Upsun](/get-started).
Puppeteer allows your application to [create screenshots](https://pptr.dev/#?product=Puppeteer&version=v13.0.1&show=api-pagescreenshotoptions), [emulate a mobile device](https://pptr.dev/#?product=Puppeteer&version=v13.0.1&show=api-pageemulateoptions), [generate PDFs](https://pptr.dev/#?product=Puppeteer&version=v13.0.1&show=api-pagepdfoptions), and much more.
# Deploy Laravel on Upsun [Manage continous observability with Blackfire](https://docs.upsun.com/get-started/stacks/laravel/blackfire.html)
[Blackfire.io](/increase-observability/application-metrics/blackfire.md) is the recommended solution
for monitoring and profiling web sites and apps.
Blackfire works seamlessly with any app built with Laravel.
Blackfire PHP SDK provides the following [integrations with
Laravel](https://docs.blackfire.io/php/integrations/laravel/index):
- [Laravel Artisan](https://docs.blackfire.io/php/integrations/laravel/artisan)
- [Laravel Horizon and queue services](https://docs.blackfire.io/php/integrations/laravel/horizon)
- [Laravel Tests](https://docs.blackfire.io/php/integrations/laravel/tests)
- [Laravel Octane](https://docs.blackfire.io/php/integrations/laravel/octane)
Please refer to the [Blackfire documentation](https://docs.blackfire.io/testing-cookbooks/tests#the-code-blackfire-yaml-code-file) to set up a `.blackfire.yml` configuration to enable custom [performance tests](https://docs.blackfire.io/testing-cookbooks/index)
and automated [builds](https://docs.blackfire.io/builds-cookbooks/index).
# Deploy Symfony on Upsun [Manage continous observability with Blackfire](https://docs.upsun.com/get-started/stacks/symfony/blackfire.html)
[Blackfire.io](/increase-observability/application-metrics/blackfire.md) is the recommended solution
for monitoring and profiling web sites and apps.
Blackfire works seamlessly with any app built with Symfony.
Blackfire PHP SDK provides the following [integrations with
Symfony](https://blackfire.io/docs/php/integrations/symfony/index):
- [Symfony HTTPClient](https://blackfire.io/docs/php/integrations/symfony/http-client)
- [Symfony Messenger](https://blackfire.io/docs/php/integrations/symfony/messenger)
- [Symfony CLI Commands Monitoring](https://blackfire.io/docs/php/integrations/symfony/cli-commands-monitoring)
- [Symfony Functional Tests Production](https://blackfire.io/docs/php/integrations/symfony/functional-tests)
A `.blackfire.yaml` file is provided within the [Symfony Templates](https://github.com/symfonycorp/platformsh-symfony-template/blob/6.2/.blackfire.yaml)
to help you bootstrap the writing of custom [performance tests](https://blackfire.io/docs/testing-cookbooks/index)
and automated [builds](https://blackfire.io/docs/builds-cookbooks/index).
You can now use composable image (BETA) to install runtimes and tools in your application container. To find out more, see the dedicated documentation page.
The Python ecosystem offers a number of web servers that can be used to deploy to Upsun.
The following examples deploy a Django project named `myapp`.
They assume a `myapp/wsgi.py` or `myapp/asgi.py` file with a callable `application`.
Adjust the examples to fit your framework and app.
## Gunicorn
[Gunicorn](https://docs.gunicorn.org/) is a Python WSGI HTTP Server for Unix
that operates on a pre-fork worker model.
The Gunicorn server is broadly compatible with various web frameworks, light on server resource usage, and fast.
To deploy with Gunicorn on Upsun ,
use one of the following examples to update your [app configuration](../../create-apps/_index.md).
The examples vary based on both your package manager (Pip, Pipenv, or Poetry)
and whether your app listens on a TCP (default) or Unix (for running behind a proxy server) socket.
For more information on upstream sockets and protocols, see the [application reference](/create-apps/app-reference/single-runtime-image.md#upstream).
The snippets below assume that Gunicorn has been added as a dependency to your `requirements.txt`, `Pipfile.lock`, or `poetry.lock`.
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:commands:start:"gunicorn -w 4 -b localhost:$PORT app.wsgi:application"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:upstream:socket_family:unixcommands:start:"gunicorn -w 4 -b unix:$SOCKET app.wsgi:application"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:commands:start:"pipenv run gunicorn -w 4 -b localhost:$PORT app.wsgi:application"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:upstream:socket_family:unixcommands:start:"pipenv run gunicorn -w 4 -b unix:$SOCKET app.wsgi:application"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:commands:start:"poetry run gunicorn -w 4 -b localhost:$PORT app.wsgi:application"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:upstream:socket_family:unixcommands:start:"poetry run gunicorn -w 4 -b unix:$SOCKET app.wsgi:application"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
### Gunicorn workers
These examples define four worker processes with `-w 4`.
For more details on what you can configure, see the [Gunicorn documentation](https://docs.gunicorn.org/en/stable/faq.html#worker-processes).
Workers can also be defined with a custom [worker class](https://docs.gunicorn.org/en/latest/settings.html#worker-class),
such as [Uvicorn](https://www.uvicorn.org/#running-with-gunicorn), [gevent](https://www.gevent.org/),
or [Tornado](https://www.tornadoweb.org/).
For example, to add a Uvicorn worker class to the pip example for Unix,
adjust the start command to the following:
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
myapp:
type: 'python:3.9'
web:
upstream:
socket_family: unix
commands:
start: "gunicorn -w 4 -k uvicorn.workers.UvicornWorker -b unix:$SOCKET app.wsgi:application"
```
## Daphne
[Daphne](https://github.com/django/daphne) is a HTTP, HTTP2 ,and WebSocket protocol server for ASGI and ASGI-HTTP,
developed to power Django Channels.
To deploy with Daphne on Upsun ,
use one of the following examples to update your [app configuration](../../create-apps/_index.md).
The examples vary based on both your package manager (Pip, Pipenv, or Poetry)
and whether your app listens on a TCP (default) or Unix (for running behind a proxy server) socket.
For more information on upstream sockets and protocols, see the [application reference](/create-apps/app-reference/single-runtime-image.md#upstream).
The snippets below assume that Daphne has been added as a dependency to your `requirements.txt`, `Pipfile.lock`, or `poetry.lock`.
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:commands:start:"daphne -p $PORT app.asgi:application"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:upstream:socket_family:unixcommands:start:"daphne -u $SOCKET app.asgi:application"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:commands:start:"pipenv run daphne -p $PORT app.asgi:application"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:upstream:socket_family:unixcommands:start:"pipenv run daphne -u $SOCKET app.asgi:application"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:commands:start:"poetry run daphne -p $PORT app.asgi:application"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:upstream:socket_family:unixcommands:start:"poetry run -u $SOCKET app.asgi:application"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
## Uvicorn
[Uvicorn](https://www.uvicorn.org/) is an ASGI web server implementation for Python.
To deploy with Uvicorn on Upsun ,
use one of the following examples to update your [app configuration](../../create-apps/_index.md).
The examples vary based on both your package manager (Pip, Pipenv, or Poetry)
and whether your app listens on a TCP (default) or Unix (for running behind a proxy server) socket.
For more information on upstream sockets and protocols, see the [application reference](/create-apps/app-reference/single-runtime-image.md#upstream).
The snippets below assume that Uvicorn has been added as a dependency to your `requirements.txt`, `Pipfile.lock`, or `poetry.lock`.
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:commands:start:"uvicorn app.asgi:application --port $PORT --workers 4"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:upstream:socket_family:unixcommands:start:"uvicorn app.asgi:application --uds $SOCKET --workers 4"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:commands:start:"pipenv run uvicorn app.asgi:application --port $PORT --workers 4"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:upstream:socket_family:unixcommands:start:"pipenv run uvicorn app.asgi:application --uds $SOCKET --workers 4"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:commands:start:"poetry run uvicorn app.asgi:application --port $PORT --workers 4"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:upstream:socket_family:unixcommands:start:"poetry run uvicorn app.asgi:application --uds $SOCKET --workers 4"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
### Uvicorn workers
These examples define four worker processes with `-w 4`.
For more recommendations on this and other settings, see the [Uvicorn documentation](https://www.uvicorn.org/settings/#timeouts).
Instead of the `-w` flag, you can also use the `WEB_CONCURRENCY` variable.
See how to [set variables](../../development/variables/set-variables.md).
## Hypercorn
[Hypercorn](https://hypercorn.readthedocs.io/) is an ASGI and WSGI web server inspired by Gunicorn.
To deploy with Hypercorn on Upsun ,
use one of the following examples to update your [app configuration](../../create-apps/_index.md).
The examples vary based on both your package manager (Pip, Pipenv, or Poetry)
and whether your app listens on a TCP (default) or Unix (for running behind a proxy server) socket.
For more information on upstream sockets and protocols, see the [application reference](/create-apps/app-reference/single-runtime-image.md#upstream).
The snippets below assume that Hypercorn has been added as a dependency to your `requirements.txt`, `Pipfile.lock`, or `poetry.lock`.
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:commands:start:"hypercorn app.asgi:application -b localhost:$PORT -w 4"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:upstream:socket_family:unixcommands:start:"hypercorn app.asgi:application -b unix:$SOCKET -w 4"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:commands:start:"pipenv run hypercorn app.asgi:application -b localhost:$PORT -w 4"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:upstream:socket_family:unixcommands:start:"pipenv run hypercorn app.asgi:application -b unix:$SOCKET -w 4"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:commands:start:"poetry run hypercorn app.asgi:application -b localhost:$PORT -w 4"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'python:3.9'web:upstream:socket_family:unixcommands:start:"poetry run hypercorn app.asgi:application -b unix:$SOCKET -w 4"locations:"/":passthru:true"/static":root:"static"expires:1hallow:true
### Hypercorn workers
These examples define four worker processes with `-w 4`.
For more details on what you can configure, see the [Hypercorn documentation](https://hypercorn.readthedocs.io/en/latest/how_to_guides/configuring.html).
Workers can also be defined with a custom [worker class](https://hypercorn.readthedocs.io/en/latest/how_to_guides/configuring.html#configuration-options),
such as Asyncio, Uvloop, or Trio.
For example, to add a Asyncio worker class to the pip example for Unix,
adjust the start command to the following:
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
myapp:
type: 'python:3.9'
web:
upstream:
socket_family: unix
commands:
start: "hypercorn app.asgi:application -b unix:$SOCKET -w 4 -k asyncio"
```
# Deploy Laravel on Upsun [Debug with Laravel Telescope](https://docs.upsun.com/get-started/stacks/laravel/laravel-telescope.html)
Laravel Telescope complements your local Laravel development environment.
With Telescope, get insight into the requests coming into your app, exceptions, log entries, database queries, queued jobs, mail, notifications, cache operations, scheduled tasks, variable dumps, and more.
To set up Laravel Telescope on your **non-production** environments,
follow these steps.
## 1. Create the APP_DEBUG variable
To add the `APP_DEBUG` & `TELESCOPE_ENABLED` variables on your project, run the following commands:
```bash {location="Terminal"}
upsun variable:create --level environment --name env:APP_DEBUG --value false
upsun variable:create --level environment --name env:TELESCOPE_ENABLED --value false
```
Note that the default values for your main environment are set to `false`.
To override them on other non-production environments, run the following commands:
```bash {location="Terminal"}
upsun variable:update -e ENVIRONMENT --value true env:APP_DEBUG
upsun variable:update -e ENVIRONMENT --value true env:TELESCOPE_ENABLED
```
## 2. Add Telescope to your project
1. Run the following Composer command:
```bash {location="Terminal"}
composer require laravel/telescope && php artisan telescope:install
```
2. Add the `install` command to your `build` hook in your app configuration,
so it's run on every deploy.
```yaml {configFile="app"}
applications:
myapp:
[...]
hooks:
build: |
set -eux
composer --no-ansi --no-interaction install --no-progress --prefer-dist --optimize-autoloader --no-dev
php artisan telescope:install
```
For more options and information on how to manage authentication for the dashboard,
see the [Laravel Telecope documentation](https://laravel.com/docs/master/telescope#installation).
## 3. Deploy the new release
To enable Telescope, push your changes to Upsun:
```bash {location="Terminal"}
git add .
git commit -m "Enable Laravel Horizon"
upsun push
```
You can now access the `/telescope` endpoint of your app.

Note
Telescope uses a gate defined in TelescopeServiceProvider.php to authorize access to the dashboard.
Check that the logic here matches your needs.
# Frameworks [Deploy Django on {{% vendor/name %}}](https://docs.upsun.com/get-started/stacks/django.html)
Note
Before you start, check out the Upsun demo app and the main Getting started guide.
They provide all of the core concepts and common commands you need to know before using the materials below.
For Django to successfully deploy and operate, **after completing the [Getting started guide](/get-started/here/_index.md)**,
you still need to make a few changes to your Upsun configuration.
## Before you begin
You need:
- [Git](https://git-scm.com/downloads).
Git is the primary tool to manage everything your app needs to run.
Push commits to deploy changes and control configuration through YAML files.
These files describe your infrastructure, making it transparent and version-controlled.
- A Upsun account.
If you don't already have one, [register for a trial account](https://auth.upsun.com/register).
You can sign up with an email address or an existing GitHub, Bitbucket, or Google account.
If you choose one of these accounts, you can set a password for your Upsun account later.
- The [Upsun CLI](/administration/cli/_index.md).
This lets you interact with your project from the command line.
You can also do most things through the [Web Console](/administration/web/_index.md).
## 1. Leverage environment variables
Your `settings.py` file may allow for environment variables to be set for common pieces of configuration.
In this case, add and commit a `.environment` file that includes those details.
```bash {location=".environment"}
export DJANGO_SETTINGS_MODULE=config.settings.production
export DJANGO_SECRET_KEY="$PLATFORM_PROJECT_ENTROPY"
export DJANGO_ALLOWED_HOSTS=".platformsh.site"
```
Warning
Not all Django apps allow for configuration in this way.
See the following sections to see how other common settings should be set on Upsun.
## 2. Configure `ALLOWED_HOSTS`
Your `settings.py` file may not allow you to use an environment variable like `DJANGO_ALLOWED_HOSTS`.
If so, to configure allowed hosts, update your `settings.py` file to include `platformsh.site`:
```py {location="settings.py"}
ALLOWED_HOSTS = [
'localhost',
'127.0.0.1',
'.platformsh.site',
]
```
Appending `.platformsh.site` to `ALLOWED_HOSTS` allows for all URLs generated for Upsun preview environments.
## 3. Upsun-specific settings
Near the bottom of your `settings.py` file, define a block that:
- Detects when Django is running on an Upsun environment
- Override previous settings
If your configuration is split into a `production.py` file for production settings, place it there instead.
```py {location="settings.py"}
# Production/Upsun settings.
if (os.getenv('PLATFORM_APPLICATION_NAME') is not None):
DEBUG = False
# Static dir.
if (os.getenv('PLATFORM_APP_DIR') is not None):
STATIC_ROOT = os.path.join(os.getenv('PLATFORM_APP_DIR'), 'static')
# Secret Key.
if (os.getenv('PLATFORM_PROJECT_ENTROPY') is not None):
SECRET_KEY = os.getenv('PLATFORM_PROJECT_ENTROPY')
# Production database configuration.
if (os.getenv('PLATFORM_ENVIRONMENT') is not None):
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.getenv('DATABASE_PATH'),
'USER': os.getenv('DATABASE_USERNAME'),
'PASSWORD': os.getenv('DATABASE_PASSWORD'),
'HOST': os.getenv('DATABASE_HOST'),
'PORT': os.getenv('DATABASE_PORT'),
},
'sqlite': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
```
This update includes a few important changes:
1. **Overwrites.** If the `PLATFORM_APPLICATION_NAME` Upsun built-in variable is found (that is, Django is running on an Upsun environment), override your previous settings.
No matter what environment type we run on Upsun, this file uses production settings for Upsun (i.e. `DEBUG = False`).
1. **Static.** `STATIC_ROOT`, and the `static` files path is updated relative to the application root on Upsun.
1. **Secret key.** All Upsun projects come with a unique hash environment variable `PLATFORM_PROJECT_ENTROPY` that can be used to update your `SECRET_KEY`.
1. **Databases.** When Django is running on an Upsun enviroment _at runtime_, it has access to service containers like databases and caches.
Every service container you configure in `.upsun/config.yaml` has a unique relationship name (`applications::relationships:`).
Upsun automatically uses this relationship name to expose connection credentials through environment variables (for example, via `RELATIONSHIPNAME_HOST`).
Update `settings.py` according to the example above (which configures a PostgreSQL service), where the relationship `database` results in environment variables that are leveraged to update the `DATABASES` setting for your application.
You can use the exact same logic to configure `CACHES` from the `rediscache` relationship using the exposed `REDISCACHE_` environment variables to setup `django_redis.cache.RedisCache`.
## 4. Start the app
In your app configuration, locate the `web:commands:start` section and update it as follows:
```yaml {configFile="app"}
applications:
myapp:
...
web:
commands:
start: "gunicorn -b unix:$SOCKET config.wsgi"
upstream:
socket_family: unix
```
Note that if your Django instance requires a different web server,
Upsun also supports [several other options](/languages/python/server.md).
## 5. Configure static assets
To access Django's static assets, you need to add a second location to the `web:locations` section of your app configuration.
Locate the `web:locations` section and add a location for `/static`:
```yaml {configFile="app"}
applications:
myapp:
...
web:
locations:
"/":
"passthru": true
"/static":
"allow": true
"expires": "1h"
"root": "static"
```
## 6. Install dependencies and builds
Instruct Upsun to install your Python and Node (if needed) dependencies.
Locate the `hooks:build` section and update it as follows:
```yaml {configFile="app"}
applications:
myapp:
...
build: |
set -eux
pip install --upgrade pip
pip install -r requirements.txt
npm install
npm run build
```
Remove the `npm` steps if not required for your app's assets.
Note that if your project uses a different package manager,
Upsun also supports [several other options](/languages/python/dependencies.md).
## 7. Configure the deploy phase
In your app configuration, locate the `deploy` section and update it as follows:
```yaml {configFile="app"}
applications:
myapp:
...
deploy: |
set -eux
python manage.py collectstatic --noinput
python manage.py migrate
```
## 8. Allow write access where needed
Since Django can require a writable locations at runtime, you need to set up writable mounts.
To do so, locate the `mounts` section (currently commented), and update it as follows:
```yaml {configFile="app"}
applications:
myapp:
...
mounts:
"/staticfiles":
source: "local"
source_path: "static_assets"
```
You can now commit all of the above changes and push to Upsun.
```bash {location="Terminal"}
git add .
git commit -m "Add changes to complete my Upsun configuration"
git push
```
## Further resources
### Documentation
- [Python documentation](/languages/python/)
- [Managing dependencies](/languages/python/dependencies)
- [Configuring web servers](/languages/python/server)
### Community content
- [Django topics](https://support.platform.sh/hc/en-us/search?utf8=%E2%9C%93&query=django)
- [Python topics](https://support.platform.sh/hc/en-us/search?utf8=%E2%9C%93&query=python)
### Blogs
- [_Up(sun) and running with Django_](https://upsun.com/blog/setting-up-django-on-upsun/)
# Add services [InfluxDB (Database service)](https://docs.upsun.com/add-services/influxdb.html)
InfluxDB is a time series database optimized for high-write-volume use cases such as logs, sensor data, and real-time analytics.
It exposes an HTTP API for client interaction. See the [InfluxDB documentation](https://docs.influxdata.com/influxdb) for more information.
## Supported versions
You can select the major and minor version.
Patch versions are applied periodically for bug fixes and the like.
When you deploy your app, you always get the latest available patches.
2.7
2.3
## Deprecated versions
The following versions are still available in your projects,
but they're at their end of life and are no longer receiving security updates from upstream.
2.2
1.8
1.7
1.3
1.2
To ensure your project remains stable in the future,
switch to a [supported version](#supported-versions).
See more information on [how to upgrade to version 2.3 or later](#upgrade-to-version-23-or-later).
## Relationship reference
For each service [defined via a relationship](#usage-example) to your application,
Upsun automatically generates corresponding environment variables within your application container,
in the ``$_`` format.
Here is example information available through the [service environment variables](/development/variables/_index.md#service-environment-variables) themselves,
or through the [``PLATFORM_RELATIONSHIPS`` environment variable](/development/variables/use-variables.md#use-provided-variables).
You can obtain the complete list of available service environment variables in your app container by running upsun ssh env.
Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the service environment variables directly rather than hard coding any values.
For some advanced use cases, you can use the PLATFORM_RELATIONSHIPS environment variable.
The structure of the PLATFORM_RELATIONSHIPS environment variable can be obtained by running upsun relationships in your terminal:
# Decode the built-in credentials object variable.exportRELATIONSHIPS_JSON=$(echo$PLATFORM_RELATIONSHIPS| base64 --decode)# Set environment variables for individual credentials.exportAPP_INFLUXDB_HOST="$(echo$RELATIONSHIPS_JSON| jq -r '.influxdb[0].host')"
## Usage example
### 1. Configure the service
To define the service, use the `influxdb` type:
```yaml {configFile="app"}
services:
# The name of the service container. Must be unique within a project.
:
type: influxdb:
```
Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service.
### 2. Define the relationship
To define the relationship, use the following configuration:
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<SERVICE_NAME>:
You can define <SERVICE_NAME> as you like, so long as it’s unique between all defined services
and matches in both the application and services configuration.
The example above leverages default endpoint configuration for relationships.
That is, it uses default endpoints behind-the-scenes, providing a relationship
(the network address a service is accessible from) that is identical to the name of that service.
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<RELATIONSHIP_NAME>:service:<SERVICE_NAME>endpoint:influxdb
You can define <SERVICE_NAME> and <RELATIONSHIP_NAME> as you like, so long as it’s unique between all defined services and relationships
and matches in both the application and services configuration.
The example above leverages explicit endpoint configuration for relationships.
applications:# The name of the app container. Must be unique within a project.myapp:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:influxdb:services:# The name of the service container. Must be unique within a project.influxdb:type:influxdb:2.7
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:influxdb:service:influxdbendpoint:influxdbservices:# The name of the service container. Must be unique within a project.influxdb:type:influxdb:2.7
### Use in app
To use the configured service in your app, add a configuration file similar to the following to your project.
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"[...]# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:influxdb:service:influxdb:type:influxdb:2.7
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"[...]# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:influxdb:service:influxdbendpoint:influxdbservice:influxdb:type:influxdb:2.7
This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory.
`myapp` has access to the `influxdb` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship)
(as per [default endpoint](/create-apps/app-reference/single-runtime-image#relationships) configuration for relationships).
From this, ``myapp`` can retrieve access credentials to the service through the [relationship environment variables](#relationship-reference).
```bash {location="myapp/.environment"}
# Set environment variables for common InfluxDB credentials.
# For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables.
export INFLUX_USER=${INFLUXDB_USERNAME}
export INFLUX_HOST=${INFLUXDB_HOST}
export INFLUX_ORG=$(echo $INFLUXDB_QUERY | jq -r ".org")
export INFLUX_TOKEN=$(echo $INFLUXDB_QUERY | jq -r ".api_token")
export INFLUX_BUCKET=$(echo $INFLUXDB_QUERY | jq -r ".bucket")
```
The above file — ``.environment`` in the ``myapp`` directory — is automatically sourced by Upsun into the runtime environment, so that the variable ``INFLUX_HOST`` can be used within the application to connect to the service.
Note that ``INFLUX_HOST``, and all [Upsun-service environment variables](/development/variables/_index.md#service-environment-variables) like ``INFLUXDBDATABASE_HOST``,
are environment-dependent.
Unlike the build produced for a given commit,
they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment.
A file very similar to this is generated automatically for your when using the ``upsun ify`` command to [migrate a codebase to Upsun](/get-started/_index.md).
## Export data
To export your data from InfluxDB, follow these steps:
1. Install and set up the [`influx` CLI](https://docs.influxdata.com/influxdb/cloud/tools/influx-cli/).
2. Connect to your InfluxDB service with the [Upsun CLI](../administration/cli/_index.md):
```bash
upsun tunnel:single
```
This opens an SSH tunnel to your InfluxDB service on your current environment and produces output like the following:
```bash
SSH tunnel opened to RELATIONSHIP_NAME at: http://127.0.0.1:30000
```
3. Get the username, password and token from the [relationship](#relationship-reference) by running the following command:
```bash
upsun relationships -P RELATIONSHIP_NAME
```
4. Adapt and run [InfluxDB's CLI export command](https://docs.influxdata.com/influxdb/v2.3/reference/cli/influx/backup/).
``` bash
influx backup --host URL_FROM_STEP_2 --token API_TOKEN_FROM_STEP_3
```
## Upgrade to version 2.3 or later
### From a previous 2.x version
From version 2.3 onward, the structure of relationships changes.
If you're using a prior 2.x version, your app might currently rely on pulling the `bucket`, `org`, `api_token`,
or `user` values available in the [`PLATFORM_RELATIONSHIPS` environment variable](#relationship-reference).
If so, to ensure your upgrade is successful, make the following changes to your connection logic:
- Rename the `user` key to `username`.
- Move the `org`, `bucket` and `api_token` keys so they're contained in a dictionary under the `query` key.
If you're relying on any other attributes connecting to InfluxDB, they remain accessible as environment variable from the [service environment variable](#relationship-reference), aside from those addressed above:
### From a 1.x version
From version 2.3 onward, InfluxDB includes an upgrade utility that can convert databases from previous versions to version 2.3 or later.
To upgrade from a 1.x version to 2.3 or later,
change the service version in your `.upsun/config.yaml` file and push your project.
Any existing data you had in your 1.x system is automatically upgraded for you into the 2.3+ system.
Note
During an upgrade from a 1.x version to a 2.3 version or later,
a new admin password and a new admin API token are automatically generated.
Previous credentials can’t be retained.
# Deploy Symfony on Upsun [Local development](https://docs.upsun.com/get-started/stacks/symfony/local.html)
When you develop a Symfony project, a significant amount of work takes place
locally rather than on an active Upsun environment. You want to ensure
that the process of local development is as close as possible to a deployed
environment.
You can achieve this through various approaches. For example, you can use
Symfony Server with tethered data.
To do so, when testing changes locally, you can connect your locally running
Symfony Server to service containers on an active Upsun environment.
This methodology has several advantages:
- It avoids installing anything on your local machine but PHP;
- It ensures that you are using the same versions of all services on your local
machine and in production.
Warning
Never use this method on the main environment as changes made on your local
machine will impact production data.
## Before you begin
You need:
- A local copy of the repository for a project running on Upsun.
You can clone an integrated source repository and set the remote branch.
To do so, run symfony cloud:project:set-remote PROJECT_ID.
- The [Symfony CLI](https://symfony.com/download)
## 1. Start your Symfony Server
To start your [Symfony
Server](https://symfony.com/doc/current/setup/symfony_server.html) locally and
display your Symfony app, run the following command:
```bash
symfony server:start -d
symfony open:local
```
This starts the Symfony Server and opens the app in your local browser.
## 2. Create the tethered connection
1. Create a new environment off of production:
```bash
symfony branch new-feature main
```
2. Open an SSH tunnel to the new environment's services:
```bash
symfony tunnel:open
````
This command returns the addresses for SSH tunnels to all of your services:
```bash
symfony tunnel:open
SSH tunnel opened to rediscache at: redis://127.0.0.1:30000
SSH tunnel opened to database at: pgsql://main:main@127.0.0.1:30001/main
Logs are written to: /Users/acmeUser/.platformsh/tunnels.log
List tunnels with: symfony tunnels
View tunnel details with: symfony tunnel:info
Close tunnels with: symfony tunnel:close
Save encoded tunnel details to the PLATFORM_RELATIONSHIPS variable using:
export PLATFORM_RELATIONSHIPS="$(symfony tunnel:info --encode)"
```
3. To expose Upsun services to your Symfony app, run the following
command:
```bash
symfony var:expose-from-tunnel
```
This automatically configures your local Symfony app to use all your
remote Upsun services (remote database, remote Redis component, etc.).
To check that you're now using remote data and components from Upsun,
reload your local app within your browser.
4. When you've finished your work,
close the tunnels to your services by running the following command:
```bash
symfony var:expose-from-tunnel --off
symfony tunnel:close --all -y
```
# Local development [Tethered](https://docs.upsun.com/get-started/here/local/tethered.html)
When you develop a project, a significant amount of work takes place
locally rather than on an active Upsun environment. You want to ensure
that the process of local development is as close as possible to a deployed
environment.
You can achieve this through various approaches. For example, you can use
Symfony Server with tethered data.
To do so, when testing changes locally, you can connect your locally running
Symfony Server to service containers on an active Upsun environment.
This methodology has several advantages:
- It avoids installing anything on your local machine but your stack runtime.
- It ensures that you are using the same versions of all services on your local
machine and in production.
Warning
Never use this method on the main environment as changes made on your local
machine will impact production data.
## 1. Start your local Server
Use the official path to start your local server locally.
## 2. Create the tethered connection
1. Create a new environment off of production:
```bash
upsun branch new-feature main
```
1. Open an SSH tunnel to the new environment's services:
```bash
upsun tunnel:open
````
This command returns the addresses for SSH tunnels to all of your services that you can then use within your local source code:
```bash
upsun tunnel:open
SSH tunnel opened to rediscache at: redis://127.0.0.1:30000
SSH tunnel opened to database at: pgsql://main:main@127.0.0.1:30001/main
Logs are written to: /Users/acmeUser/.upsun/tunnels.log
List tunnels with: upsun tunnels
View tunnel details with: upsun tunnel:info
Close tunnels with: upsun tunnel:close
Save encoded tunnel details to the PLATFORM_RELATIONSHIPS variable using:
export PLATFORM_RELATIONSHIPS="$(upsun tunnel:info --encode)"
```
1. When you've finished your work,
close the tunnels to your services by running the following command:
```bash
upsun tunnel:close --all -y
```
# Frameworks [Deploy Flask on {{% vendor/name %}}](https://docs.upsun.com/get-started/stacks/flask.html)
Note
Before you start, check out the Upsun demo app and the main Getting started guide.
They provide all of the core concepts and common commands you need to know before using the materials below.
For Flask to successfully deploy and operate, **after completing the [Getting started guide](/get-started/here/_index.md)**,
you still need to make a few changes to your Upsun configuration.
## Before you begin
You need:
- [Git](https://git-scm.com/downloads).
Git is the primary tool to manage everything your app needs to run.
Push commits to deploy changes and control configuration through YAML files.
These files describe your infrastructure, making it transparent and version-controlled.
- A Upsun account.
If you don't already have one, [register for a trial account](https://auth.upsun.com/register).
You can sign up with an email address or an existing GitHub, Bitbucket, or Google account.
If you choose one of these accounts, you can set a password for your Upsun account later.
- The [Upsun CLI](/administration/cli/_index.md).
This lets you interact with your project from the command line.
You can also do most things through the [Web Console](/administration/web/_index.md).
## 1. Leverage environment variables
The CLI generated a `.environment` file during the Getting started guide.
Notice it has already created some environmental variables for you to connect to your database service.
```bash {location=".environment"}
export RELATIONSHIPS_JSON="$(echo $PLATFORM_RELATIONSHIPS | base64 --decode)"
# Set database environment variables
export DB_HOST="$(echo $RELATIONSHIPS_JSON | jq -r '.postgresql[0].host')"
export DB_PORT="$(echo $RELATIONSHIPS_JSON | jq -r '.postgresql[0].port')"
export DB_DATABASE="$(echo $RELATIONSHIPS_JSON | jq -r '.postgresql[0].path')"
export DB_USERNAME="$(echo $RELATIONSHIPS_JSON | jq -r '.postgresql[0].username')"
export DB_PASSWORD="$(echo $RELATIONSHIPS_JSON | jq -r '.postgresql[0].password')"
export DB_CONNECTION="$(echo $RELATIONSHIPS_JSON | jq -r '.postgresql[0].scheme')"
export DATABASE_URL="postgresql://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_DATABASE}"
```
To configure all the environment variables Flask needs to run smoothly, follow these steps.
1. Set the `FLASK_APP` environment variable to specify how to load the app.
```bash {location=".environment"}
export FLASK_APP="autoapp.py"
```
The above example uses the file `autoapp.py` as the main entry.
Adjust according to your situation.
2. Set the `FLASK_ENV` environment variable to enable behaviors based on the environment type.
Upsun provides information about what type of environment the app is running in via the `PLATFORM_ENVIRONMENT_TYPE` environment variable.
Its values can be ``production``, ``development``, or ``staging``.
Use this information to set the value for `FLASK_ENV`.
```bash {location=".environment"}
export FLASK_ENV="${PLATFORM_ENVIRONMENT_TYPE}"
```
Several other environmental variables need to change based on the environment type.
Leverage the information in `PLATFORM_ENVIRONMENT_TYPE` for these other variables too.
3. Set the `FLASK_DEBUG` environment variable to ``1`` (enabled) if you're not running in production.
```bash {location=".environment"}
export FLASK_DEBUG=$( [ "${PLATFORM_ENVIRONMENT_TYPE}" = "production" ] && echo 0 || echo 1)
```
4. Do the same for `LOG_LEVEL`.
```bash {location=".environment"}
export LOG_LEVEL=$( [ "${PLATFORM_ENVIRONMENT_TYPE}" = "production" ] && echo "info" || echo "debug")
```
5. Set the `SEND_FILE_MAX_AGE_DEFAULT` to ``0`` (disabled) if you're not in production, but a higher value if you are.
```bash {location=".environment"}
export SEND_FILE_MAX_AGE_DEFAULT=$( [ "${PLATFORM_ENVIRONMENT_TYPE}" = "production" ] && echo 31556926 || echo 0)
```
6. Optional: You may also need to set a `SECRET_KEY` environment variable.
It's used for securely signing the session cookie and can be used for any other security-related needs by extensions or your app.
It usually is a long random string.
Set the `SECRET_KEY` environment variable to leverage the [`PLATFORM_PROJECT_ENTROPY` variable](/development/variables/use-variables#use-provided-variables) provided by Upsun:
```bash {location=".environment"}
export SECRET_KEY="${PLATFORM_PROJECT_ENTROPY}"
```
Your `.environment` file should now look similar to the following:
```bash {location=".environment"}
# Set database environment variables
export DB_HOST="$POSTGRESQL_HOST"
export DB_PORT="$POSTGRESQL_PORT"
export DB_PATH="$POSTGRESQL_PATH"
export DB_USERNAME="$POSTGRESQL_USERNAME"
export DB_PASSWORD="$POSTGRESQL_PASSWORD"
export DB_SCHEME="postgresql"
export DATABASE_URL="${DB_SCHEME}://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_PATH}"
export FLASK_ENV="${PLATFORM_ENVIRONMENT_TYPE}"
export FLASK_DEBUG=$( [ "${PLATFORM_ENVIRONMENT_TYPE}" = "production" ] && echo 0 || echo 1)
export LOG_LEVEL=$( [ "${PLATFORM_ENVIRONMENT_TYPE}" = "production" ] && echo "info" || echo "debug")
export SEND_FILE_MAX_AGE_DEFAULT=$( [ "${PLATFORM_ENVIRONMENT_TYPE}" = "production" ] && echo 31556926 || echo 0)
export SECRET_KEY="${PLATFORM_PROJECT_ENTROPY}"
```
## 2. Configure static assets
You need to add some writable disk space to hold the static assets that `flask-static-digest` generates and `npm` builds.
To do so, define the `.//static` directory as [a mount](/create-apps/app-reference/single-runtime-image#mounts).
In your app configuration, locate the section dedicated to mounts and update it as follows:
```yaml {configFile="app"}
applications:
myapp:
...
mounts:
"/static":
source: "storage"
source_path: "static_assets"
```
Replace `` with the `app_name` you defined when creating your Flask project.
## 3. Install dependencies and builds
Instruct Upsun to automatically run `npm install` in addition to installing your Python dependencies
when building the application container.
To do so, customize your [build hook](/create-apps/hooks/hooks-comparison.html#build-hook).
In your app configuration, locate the section dedicated to it and update it as follows:
```yaml {configFile="app"}
applications:
myapp:
...
# Hooks allow you to customize your code/environment as the project moves through the build and deploy stages
# More information: https://docs.upsun.com/create-apps/app-reference.html#hooks
hooks:
# The build hook is run after any build flavor.
# More information: https://docs.upsun.com/create-apps/hooks/hooks-comparison.html#build-hook
build: |
set -eux
pip install -r requirements.txt
```
The Upsun CLI automatically added `pip install -r requirements.txt` to your build hook configuration when you
[configured your Upsun project](/get-started/here/configure/_index.md).
If you want `pip` to be upgraded first to the latest version, add `pip install --upgrade pip` to the above line.
Then, add `npm install`:
```yaml {configFile="app"}
applications:
myapp:
...
# Hooks allow you to customize your code/environment as the project moves through the build and deploy stages
# More information: https://docs.upsun.com/create-apps/app-reference.html#hooks
hooks:
# The build hook is run after any build flavor.
# More information: https://docs.upsun.com/create-apps/hooks/hooks-comparison.html#build-hook
build: |
set -eux
pip install --upgrade pip
pip install -r requirements.txt
npm install
```
Note that if your project uses a different package manager, Upsun also supports [several other options](/languages/python/dependencies.md).
## 4. Configure the deploy phase
Instruct Upsun to automatically run `npm run build` when building the application container.
To do so, customize your [deploy hook](/create-apps/hooks/hooks-comparison.html#deploy-hook).
In your app configuration, locate the section dedicated to it:
```yaml {configFile="app"}
applications:
myapp:
...
# Hooks allow you to customize your code/environment as the project moves through the build and deploy stages
# More information: https://docs.upsun.com/create-apps/app-reference.html#hooks
hooks:
...
# The deploy hook is run after the app container has been started, but before it has started accepting requests.
# More information: https://docs.upsun.com/create-apps/hooks/hooks-comparison.html#deploy-hook
deploy: |
set -eux
# echo 'Put your deploy command here'
```
Add `npm run build`:
```yaml {configFile="app"}
applications:
myapp:
...
# Hooks allow you to customize your code/environment as the project moves through the build and deploy stages
# More information: https://docs.upsun.com/create-apps/app-reference.html#hooks
hooks:
...
# The deploy hook is run after the app container has been started, but before it has started accepting requests.
# More information: https://docs.upsun.com/create-apps/hooks/hooks-comparison.html#deploy-hook
deploy: |
set -eux
npm run build
```
## 5. Configure the web server
[Configure the web server](/create-apps/_index.md#configure-whats-served) running in front of your app to define how your app handles dynamic requests.
To do so, in your app configuration, locate the section dedicated to the web server:
```yaml {configFile="app"}
applications:
myapp:
...
# The web key configures the web server running in front of your app.
# More information: https://docs.upsun.com/create-apps/app-reference.html#web
web:
# Commands are run once after deployment to start the application process.
# More information: https://docs.upsun.com/create-apps/app-reference.html#web-commands
```
To add a basic Flask server, replace the default information added by the Upsun CLI with `flask run -p $PORT`.
Also, change the `socket_family` value from `unix` to `tcp`:
```yaml {configFile="app"}
applications:
myapp:
...
# The web key configures the web server running in front of your app.
# More information: https://docs.upsun.com/create-apps/app-reference.html#web
web:
# Commands are run once after deployment to start the application process.
# More information: https://docs.upsun.com/create-apps/app-reference.html#web-commands
commands:
start: "flask run -p $PORT"
upstream:
socket_family: tcp
```
You can now commit all of the above changes and push to Upsun.
```bash {location="Terminal"}
git add .
git commit -m "Add changes to complete my Upsun configuration"
git push
```
Note that if your Flask project requires a different web server,
Upsun also supports [several other options](/languages/python/server.md), including Gunicorn, Daphne,
Uvicorn, and Hypercorn.
If you use Pip, make sure you add your chosen web server to your `requirements.txt` file.
## 6. Handle database migrations
### Prepare database migrations
If you have a new Flask project that uses [Flask-migrate](https://flask-migrate.readthedocs.io/en/latest/),
or an existing app but need to set up the initial migrations, you can do so using the database service you created earlier.
To do so, follow these steps.
1. Set up a virtual environment where your project can run:
```bash {location="Terminal"}
python3 -m venv env && source venv/bin/activate
```
2. Just like in your build hook, update pip and install the requirements:
```bash {location="Terminal"}
pip install --upgrade pip && pip install -r requirements.txt
```
3. Set up a way for your local instance of Flask to communicate with your database service:
```bash {location="Terminal"}
upsun tunnel:open -y
```
This opens an SSH tunnel to all the services for the app.
You can use this connection to allow your local instance to communicate with live services as if they too were local.
To do so, you need to configure more environment variables.
4. Reopen your `.environment` file.
Note the use of the `$PLATFORM_RELATIONSHIPS` environment variable to retrieve information about services and their credentials.
The tunnel you created gives you access to that same data,
allowing you to generate a local `PLATFORM_RELATIONSHIPS` environment variable containing the same information.
Set the following environment variable:
```bash {location=".environment"}
export PLATFORM_RELATIONSHIPS="$(upsun tunnel:info --encode)"
```
Since you now have this environmental variable set locally, you can reuse your `.environment` file for Upsun to recreate
many of the other environmental variables you need to run locally.
5. Set the following environment variables as they aren't set via ``PLATFORM_RELATIONSHIPS``:
```bash {location=".environment"}
export PLATFORM_ENVIRONMENT_TYPE=production
export PORT=8888
export PLATFORM_PROJECT_ENTROPY=$(openssl rand -base64 32)
```
6. Source your `.environment` file to finish setting up all the environmental variables in your current bash:
```bash {location="Terminal"}
source ./.environment
```
You now have everything you need for Flask-Migrate to be able to connect to the database and generate your migration files.
### Generate database migrations
1. Initiate the migrations directory and prepare for the ``migrate`` command:
```bash {location="Terminal"}
flask db init
```
2. Generate your migrations:
```bash {location="Terminal"}
flask db migrate
```
3. Commit your generated migrations:
```bash {location="Terminal"}
git add migrations/* && git commit -m "Adds migrations"
```
4. Instruct Upsun to run the Flask-migrate upgrade command when deploying
so any migration changes are automatically applied.
To do so, re-open your `.upsun/config.yaml` file.
Locate the `deploy` hook where you added `npm run build` previously and update it as follows:
```yaml {configFile="app"}
applications:
myapp:
...
# Hooks allow you to customize your code/environment as the project moves through the build and deploy stages
# More information: https://docs.upsun.com/create-apps/app-reference.html#hooks
hooks:
...
# The deploy hook is run after the app container has been started, but before it has started accepting requests.
# More information: https://docs.upsun.com/create-apps/hooks/hooks-comparison.html#deploy-hook
deploy: |
set -eux
npm run build
flask db upgrade
```
5. Commit all your changes and push to Upsun.
```bash {location="Terminal"}
git add .
git commit -m "Add changes to complete my Upsun configuration"
git push
```
## Further resources
### Documentation
- [Python documentation](/languages/python/)
- [Managing dependencies](/languages/python/dependencies)
- [Configuring web servers](/languages/python/server)
### Community content
- [Flask topics](https://support.platform.sh/hc/en-us/search?utf8=%E2%9C%93&query=flask)
- [Python topics](https://support.platform.sh/hc/en-us/search?utf8=%E2%9C%93&query=python)
### Blogs
- [Up(sun) and running with Django](https://upsun.com/blog/setting-up-django-on-upsun/)
# Add services [Kafka (Message queue service)](https://docs.upsun.com/add-services/kafka.html)
Apache Kafka is an open-source stream-processing software platform.
It is a framework for storing, reading and analyzing streaming data. See the [Kafka documentation](https://kafka.apache.org/documentation) for more information.
## Supported versions
You can select the major and minor version.
Patch versions are applied periodically for bug fixes and the like.
When you deploy your app, you always get the latest available patches.
3.7
3.6
3.4
3.2
## Relationship reference
For each service [defined via a relationship](#usage-example) to your application,
Upsun automatically generates corresponding environment variables within your application container,
in the ``$_`` format.
Here is example information available through the [service environment variables](/development/variables/_index.md#service-environment-variables) themselves,
or through the [``PLATFORM_RELATIONSHIPS`` environment variable](/development/variables/use-variables.md#use-provided-variables).
You can obtain the complete list of available service environment variables in your app container by running ``upsun ssh env``.
Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the [service environment variables](/development/variables/_index.md#service-environment-variables) directly rather than hard coding any values.
For some advanced use cases, you can use the PLATFORM_RELATIONSHIPS environment variable.
The structure of the PLATFORM_RELATIONSHIPS environment variable can be obtained by running upsun relationships in your terminal:
# Decode the built-in credentials object variable.exportRELATIONSHIPS_JSON=$(echo$PLATFORM_RELATIONSHIPS| base64 --decode)# Set environment variables for individual credentials.exportAPP_KAFKA_HOST="$(echo$RELATIONSHIPS_JSON| jq -r '.kafka[0].host')"
## Usage example
### 1. Configure the service
To define the service, use the ``kafka`` type:
```yaml {configFile="app"}
services:
# The name of the service container. Must be unique within a project.
:
type: kafka:
```
Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service.
### 2. Define the relationship
To define the relationship, use the following configuration:
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<SERVICE_NAME>:
You can define <SERVICE_NAME> as you like, so long as it’s unique between all defined services
and matches in both the application and services configuration.
The example above leverages default endpoint configuration for relationships.
That is, it uses default endpoints behind-the-scenes, providing a relationship
(the network address a service is accessible from) that is identical to the name of that service.
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<RELATIONSHIP_NAME>:service:<SERVICE_NAME>endpoint:kafka
You can define <SERVICE_NAME> and <RELATIONSHIP_NAME> as you like, so long as it’s unique between all defined services and relationships
and matches in both the application and services configuration.
The example above leverages explicit endpoint configuration for relationships.
applications:# The name of the app container. Must be unique within a project.myapp:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:kafka:services:# The name of the service container. Must be unique within a project.kafka:type:kafka:3.7
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:kafka:service:kafkaendpoint:kafkaservices:# The name of the service container. Must be unique within a project.kafka:type:kafka:3.7
### Use in app
To use the configured service in your app, add a configuration file similar to the following to your project.
The file static/files/fetch/examples/python/kafka was not found. Did you define it in docs/data/remote-examples to be downloaded?
## With the ruby-kafka gem# Producerrequire"kafka"kafka=Kafka.new(["kafka.internal:9092"],client_id:"my-application")kafka.deliver_message("Hello, World!",topic:"greetings")# Consumerkafka.each_message(topic:"greetings")do|message|putsmessage.offset,message.key,message.valueend
# Frameworks [Deploy WordPress on {{% vendor/name %}}](https://docs.upsun.com/get-started/stacks/wordpress.html)
Note
Before you start, check out the Upsun demo app
and the main Getting started guide.
They provide all the core concepts and common commands you need to know before using the following materials.
For WordPress to successfully deploy and operate, **after completing the [Getting started guide](/get-started/here/_index.md)**,
you still need to add some required files and make a few changes to your Upsun configuration.
## Before you begin
You need:
- [Git](https://git-scm.com/downloads).
Git is the primary tool to manage everything your app needs to run.
Push commits to deploy changes and control configuration through YAML files.
These files describe your infrastructure, making it transparent and version-controlled.
- A Upsun account.
If you don't already have one, [register for a trial account](https://auth.upsun.com/register).
You can sign up with an email address or an existing GitHub, Bitbucket, or Google account.
If you choose one of these accounts, you can set a password for your Upsun account later.
- The [Upsun CLI](/administration/cli/_index.md).
This lets you interact with your project from the command line.
You can also do most things through the [Web Console](/administration/web/_index.md).
Assumptions
There are many ways you can set up a WordPress site or Upsun project.
The instructions on this page were designed based on the following assumptions:
You are building a composer-based WordPress site using John P Bloch’s WordPress Composer Fork.
You do not have a composer.json file, or are comfortable making changes to your existing version.
You selected PHP as your runtime, and MariaDB as a service during the Getting Started guide. It’s also assumed that while using the Getting Started guide you named the project myapp, which you will notice is the top-level key in all configuration below.
## 1. Add required files
To ensure you have all the required files and directories in your project, follow these steps:
1. Copy the following files from the [WordPress Composer template](https://github.com/platformsh-templates/wordpress-composer/)
and add them to the root of your project:
- The [composer.json](https://raw.githubusercontent.com/platformsh-templates/wordpress-composer/61da65da21039b280b588642cd329a2eb253e472/composer.json) file declares project dependencies and specifies project settings and metadata for [Composer](https://getcomposer.org/) to use
- The [wp-cli.yml](https://github.com/platformsh-templates/wordpress-composer/blob/61da65da21039b280b588642cd329a2eb253e472/wp-cli.yml) file contains the configuration values, related to your site, for the [WordPress CLI](https://wp-cli.org/) to use
- The [wp-config.php](https://github.com/platformsh-templates/wordpress-composer/blob/61da65da21039b280b588642cd329a2eb253e472/wp-config.php) file contains your site's base configuration details, such as database connection information
2. Optional: To support non-public plugins, add a `plugins` directory to your project.
To ensure Git tracks empty folders, add a `plugins/.gitkeep` file as well.
3. Add and commit your changes.
```bash {location="Terminal"}
git add .
git commit -m "Add files and directory"
git push
```
Now that you have pushed all the necessary files and directories to Upsun,
make the following changes to your `./.upsun/config.yaml` file.
## 2. Configure your root location
Locate the `web:locations` section and update the root (`/`) location as follows:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'php:8.3'
web:
locations:
"/":
passthru: "/index.php"
root: "wordpress"
index:
- "index.php"
expires: 600
scripts: true
allow: true
rules:
^/license\.text$:
allow: false
^/readme\.html$:
allow: false
```
Note
If you’re migrating your site, you may already have a composer.json file.
You may even have generated your own instead of starting from the Platform.sh template version.
If so, you may also have added a wordpress-install-dir property for extras in your composer.json file.
In this case, set root: to the name of the directory where you are installing WordPress.
## 3. Set up a location for uploads
WordPress needs a writable location to store uploaded media.
To set one up, follow these steps:
1. Create the location.
To do so, add a `/wp-content/uploads` location as follows:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'php:8.3'
web:
locations:
"/":
passthru: "/index.php"
root: "wordpress"
index:
- "index.php"
expires: 600
scripts: true
allow: true
rules:
^/license\.text$:
allow: false
^/readme\.html$:
allow: false
"/wp-content/uploads":
root: "wordpress/wp-content/uploads"
scripts: false
allow: false
rules:
'(?
To do so, locate the `mounts:` section that is commented it out, and update it as follows:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'php:8.3'
...
mounts:
"wordpress/wp-content/uploads":
source: storage
source_path: "uploads"
```
Note
If you have designated a different directory through the wordpress-install-dir property in your composer.json file, update the
mount location accordingly.
## 4. Install dependencies during the build hook
To ensure your Composer dependencies are installed during the [build stage](/learn/overview/build-deploy.md#the-build),
locate the `build:` section (below the `hooks:` section).
Update the `build:` section as follows:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'php:8.3'
...
hooks:
build: |
set -eux
composer install --prefer-dist --optimize-autoloader --apcu-autoloader --no-progress --no-ansi --no-interaction
rsync -a plugins/ wordpress/wp-content/plugins/
```
You can adjust the `composer install` command to meet your specific requirements.
If you aren't using the `plugins` directory to manage non-public plugins, remove the `rsync` command.
## 5. Launch tasks during the deploy hook
Some tasks need to be performed after the images for our application are built,
but before the newly built application can receive requests.
Therefore, the best time to launch them is during the [deploy hook](/learn/overview/build-deploy.md#deploy-steps).
Such tasks include:
- Flushing the object cache, which might have changed between current production and newly deployed changes
- Running the WordPress database update procedure, in case core is being updated with the newly deployed changes
- Running any due cron jobs
To launch these tasks during the deploy hook,
locate the `deploy:` section (below the `build:` section).
Update the `deploy:` section as follows:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'php:8.3'
...
hooks:
deploy: |
set -eux
# Flushes the object cache
wp cache flush
# Runs the WordPress database update procedure
wp core update-db
# Runs all due cron events
wp cron event run --due-now
```
## 6. Configure your default route
Next, instruct the [router](learn/overview/structure.md#router) how to handle requests to your WordPress app.
To do so, locate the `routes:` section, and beneath it, the `"https://{default}/":` route.
Update the route as follows:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'php:8.3'
...
routes:
"https://{default}/":
type: upstream
upstream: "myapp:http"
cache:
enabled: true
cookies:
- '/^wordpress_*/'
- '/^wp-*/'
```
Matching the application name `myapp` with the `upstream` definition `myapp:http` is the most important setting to ensure at this stage.
If these strings aren't the same, the WordPress deployment will not succeed.
## 7. Update your MariaDB service relationship
You need to update the name used to represent the [relationship](/create-apps/app-reference/single-runtime-image.md#relationships) between your app and your MariaDB service.
To do so, locate the `relationships:` top-level property.
Update the relationship for the database service as follows:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'php:8.3'
# ...
relationships:
database: "mariadb:mysql"
```
You can now commit all the changes made to `.upsun/config.yaml` and push to Upsun.
```bash {location="Terminal"}
git add .
git commit -m "Add changes to complete my Upsun configuration"
git push
```
## Further resources
### Documentation
- [PHP documentation](/languages/php/)
- [Extensions](/languages/php/extensions)
- [Performance tuning](/languages/php/tuning)
- [PHP-FPM sizing](/languages/php/fpm)
- [Authenticated Composer](/languages/php/composer-auth)
### Community content
- [PHP topics](https://support.platform.sh/hc/en-us/search?utf8=%E2%9C%93&query=php)
- [WordPress topics](https://support.platform.sh/hc/en-us/search?utf8=%E2%9C%93&query=wordpress)
### Blogs
- [To Upsun, a WordPress migration story](https://upsun.com/blog/to-upsun-a-wordpress-migration-story/)
# Frameworks [Pimcore PaaS](https://docs.upsun.com/get-started/stacks/pimcore.html)
[Pimcore](https://pimcore.com/) is an open-source digital platform that aggregates, enriches, and manages enterprise data.
It provides up-to-date, consistent, and personalized experiences to customers.
In a seamlessly integrated platform, Pimcore offers a centralized solution for Product Information Management, Master Data Management, Digital Asset Management, Customer Data Platforms, Digital Experience Platforms/Content Management Systems, and digital commerce.
Pimcore's PaaS solution is powered by Platform.sh, creators of Upsun.
For more information, see [Pimcore's documentation](https://pimcore.com/docs/platform/next/Paas/).# Frameworks [Shopware PaaS](https://docs.upsun.com/get-started/stacks/shopware.html)
[Shopware](https://www.shopware.com/) is an e-commerce platform to power your online business by offering top-of-the-line performance, agility, and security.
Shopware's PaaS solution is powered by Platform.sh, creators of Upsun.
For more information, see [Shopware's documentation](https://developer.shopware.com/docs/products/paas/).# Add services [Memcached (Object cache)](https://docs.upsun.com/add-services/memcached.html)
Memcached is a simple in-memory object store well-suited for application level caching.
See the [Memcached documentation](https://memcached.org) for more information.
Both Memcached and Redis can be used for application caching. As a general rule, Memcached is simpler and thus more widely supported while Redis is more robust. Upsun recommends using Redis if possible but Memcached is fully supported if an application favors that cache service.
## Supported versions
You can select the major and minor version.
Patch versions are applied periodically for bug fixes and the like.
When you deploy your app, you always get the latest available patches.
1.6
1.5
1.4
## Relationship reference
For each service [defined via a relationship](#usage-example) to your application,
Upsun automatically generates corresponding environment variables within your application container,
in the ``$_`` format.
Here is example information available through the [service environment variables](/development/variables/_index.md#service-environment-variables) themselves,
or through the [``PLATFORM_RELATIONSHIPS`` environment variable](/development/variables/use-variables.md#use-provided-variables).
You can obtain the complete list of available service environment variables in your app container by running upsun ssh env.
Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the service environment variables directly rather than hard coding any values.
For some advanced use cases, you can use the PLATFORM_RELATIONSHIPS environment variable.
The structure of the PLATFORM_RELATIONSHIPS environment variable can be obtained by running upsun relationships in your terminal:
# Decode the built-in credentials object variable.exportRELATIONSHIPS_JSON=$(echo$PLATFORM_RELATIONSHIPS| base64 --decode)# Set environment variables for individual credentials.exportAPP_MEMCACHED_HOST="$(echo$RELATIONSHIPS_JSON| jq -r '.memcached[0].host')"
## Usage example
### 1. Configure the service
To define the service, use the ``memcached`` type:
```yaml {configFile="app"}
services:
# The name of the service container. Must be unique within a project.
:
type: memcached:
```
Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service.
### 2. Define the relationship
To define the relationship, use the following configuration:
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<SERVICE_NAME>:
You can define <SERVICE_NAME> as you like, so long as it’s unique between all defined services
and matches in both the application and services configuration.
The example above leverages default endpoint configuration for relationships.
That is, it uses default endpoints behind-the-scenes, providing a relationship
(the network address a service is accessible from) that is identical to the name of that service.
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<RELATIONSHIP_NAME>:"<SERVICE_NAME>:memcached"
You can define <SERVICE_NAME> and <RELATIONSHIP_NAME> as you like, so long as it’s unique between all defined services and relationships
and matches in both the application and services configuration.
The example above leverages explicit endpoint configuration for relationships.
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# PHP extensions.runtime:extensions:- memcached# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<SERVICE_NAME>:
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# PHP extensions.runtime:extensions:- memcached# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<RELATIONSHIP_NAME>:"<SERVICE_NAME>:memcached"
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Build dependencies per runtime.dependencies:python:python-memcached:'*'# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<SERVICE_NAME>:
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Build dependencies per runtime.dependencies:python:python-memcached:'*'# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<RELATIONSHIP_NAME>:"<SERVICE_NAME>:memcached"
applications:# The name of the app container. Must be unique within a project.myapp:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:memcached:services:# The name of the service container. Must be unique within a project.memcached:type:memcached:1.6
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:memcached:"memcached:memcached"services:# The name of the service container. Must be unique within a project.memcached:type:memcached:1.6
### Use in app
To use the configured service in your app, add a configuration file similar to the following to your project.
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"# PHP extensions.runtime:extensions:- memcached[...]# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:memcached:service:memcached:type:memcached:1.6
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"# PHP extensions.runtime:extensions:- memcached[...]# Relationships enable access from this app to a given service.# See the Application reference for all options for defining relationships and endpoints.relationships:memcached:service:memcachedendpoint:memcachedservice:memcached:type:memcached:1.6
This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory.
`myapp` has access to the `influxdb` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship)
(as per [default endpoint](/create-apps/app-reference/single-runtime-image#relationships) configuration for relationships).
From this, ``myapp`` can retrieve access credentials to the service through the [relationship environment variables](#relationship-reference).
```bash {location="myapp/.environment"}
# Surface a Memcached connection string for use in app.
# For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables.
export CACHE_URL="${MEMCACHED_HOST}:${MEMCACHED_PORT}"
```
The above file — ``.environment`` in the ``myapp`` directory — is automatically sourced by Upsun into the runtime environment, so that the variable ``CACHE_URL`` can be used within the application to connect to the service.
Note that ``CACHE_URL``, and all Upsun [service environment variables](/development/variables/_index.md#service-environment-variables) like ``MEMCACHEDCACHE_HOST``, are environment-dependent.
Unlike the build produced for a given commit,
they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment.
A file very similar to this is generated automatically for your when using the ``upsun ify`` command to [migrate a codebase to Upsun](/get-started/_index.md).
## Accessing Memcached directly
To access the Memcached service directly you can use `netcat` as Memcached doesn't have a dedicated client tool.
Assuming your Memcached relationship is named `memcached`, the host name `MEMCACHED_HOST` and port number `MEMCACHED_PORT` obtained from the [service environment variable](#relationship-reference) would be `memcached.internal` and `11211`.
Open an [SSH session](/development/ssh/_index.md) and access the Memcached server as follows:
```bash {location="Terminal"}
netcat memcached.internal 11211
```
You can obtain the complete list of available service environment variables in your app container by running ``upsun ssh env``.
Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the [service environment variables](/development/variables/_index.md#service-environment-variables) directly rather than hard coding any values.
# Manage resources [Project build resources](https://docs.upsun.com/manage-resources/build-resources.html)
When you push changes through Git, your applications are first built, then deployed.
During the build process, Upsun creates a build image for each of your application, as a dedicated build container, and runs your build hooks inside that build container.
The duration of the build process is directly linked to the amount of resources (CPU and RAM) allocated to that build container.
Every Upsun project includes a fixed amount of build resources per month:
- 2.5 hours of build CPU
- 5 hours of build memory
You can adjust the amount of build resources that a project can use.
Expand the Project Setting accordion and click Resources.
Enter the amount of CPU and RAM that your build containers can use.
Click Save.
Run the following command:
upsun resources:build:set
Enter the amount of CPU.
Enter the amount of RAM.
Additional build resources (CPU and RAM) are billed by the hour.
For more information on the costs incurred, see the [Upsun pricing page](https://upsun.com/pricing/).
Note
Make sure that your build process supports using extra build resources.
Otherwise, the duration of your builds will remain the same despite adding more resources.
# Add services [MongoDB (Database service)](https://docs.upsun.com/add-services/mongodb.html)
MongoDB is a cross-platform, document-oriented database.
For more information on using MongoDB, see MongoDB’s own documentation.
## Supported versions
You can select the major and minor version.
Patch versions are applied periodically for bug fixes and the like.
When you deploy your app, you always get the latest available patches.
7.0
6.0
5.0
4.4
### Deprecated versions
The following versions are [deprecated](/glossary.html#deprecated-versions).
They're available, but they aren't receiving security updates from upstream and aren't guaranteed to work.
They'll be removed in the future,
so migrate to one of the [supported versions](#supported-versions).
4.2
4.0
### Legacy edition
Previous non-Enterprise versions are available in your projects (and are listed below),
but they're at their [end of life](https://www.mongodb.com/support-policy/legacy)
and are no longer receiving security updates from upstream.
Warning
Downgrades of MongoDB aren’t supported.
MongoDB updates its own data files to a new version automatically but can’t downgrade them.
If you want to experiment with a later version without committing to it use a preview environment.
### Deprecated versions
The following versions are [deprecated](/glossary.html#deprecated-versions).
They're available, but they aren't receiving security updates from upstream and aren't guaranteed to work.
They'll be removed in the future,
so migrate to one of the [supported versions](#supported-versions).
4.0.3
3.6
3.4
3.2
3.0
## Relationship reference
For each service [defined via a relationship](#usage-example) to your application,
Upsun automatically generates corresponding environment variables within your application container,
in the ``$_`` format.
Here is example information available through the [service environment variables](/development/variables/_index.md#service-environment-variables) themselves,
or through the [``PLATFORM_RELATIONSHIPS`` environment variable](/development/variables/use-variables.md#use-provided-variables).
You can obtain the complete list of available service environment variables in your app container by running upsun ssh env.
Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the service environment variables directly rather than hard coding any values.
For some advanced use cases, you can use the PLATFORM_RELATIONSHIPS environment variable.
The structure of the PLATFORM_RELATIONSHIPS environment variable can be obtained by running upsun relationships in your terminal:
# Decode the built-in credentials object variable.exportRELATIONSHIPS_JSON=$(echo$PLATFORM_RELATIONSHIPS| base64 --decode)# Set environment variables for individual credentials.exportAPP_MONGODBDATABASE_HOST="$(echo$RELATIONSHIPS_JSON| jq -r '.mongodb[0].host')"
## Usage example
### Enterprise edition example
#### 1. Configure the service
To define the service, use the ``mongodb-enterprise`` type:
```yaml {configFile="app"}
services:
# The name of the service container. Must be unique within a project.
:
type: mongodb-enterprise:
```
Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service.
#### 2. Define the relationship
To define the relationship, use the following configuration:
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<SERVICE_NAME>:
You can define <SERVICE_NAME> as you like, so long as it’s unique between all defined services
and matches in both the application and services configuration.
The example above leverages default endpoint configuration for relationships.
That is, it uses default endpoints behind-the-scenes, providing a relationship
(the network address a service is accessible from) that is identical to the name of that service.
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<RELATIONSHIP_NAME>:service:<SERVICE_NAME>endpoint:mongodb
You can define <SERVICE_NAME> and <RELATIONSHIP_NAME> as you like, so long as it’s unique between all defined services and relationships
and matches in both the application and services configuration.
The example above leverages explicit endpoint configuration for relationships.
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# PHP extensions.runtime:extensions:- mongodb# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<SERVICE_NAME>:
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# PHP extensions.runtime:extensions:- mongodb# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<RELATIONSHIP_NAME>:service:<SERVICE_NAME>endpoint:mongodb
applications:# The name of the app container. Must be unique within a project.myapp:# PHP extensions.runtime:extensions:- mongodb# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:mongodb-enterprise:services:# The name of the service container. Must be unique within a project.mongodb-enterprise:type:mongodb-enterprise:7.0
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# PHP extensions.runtime:extensions:- mongodb# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:mongodb-enterprise:service:mongodb-enterpriseendpoint:mongodbservices:# The name of the service container. Must be unique within a project.mongodb-enterprise:type:mongodb-enterprise:7.0
### Legacy edition example
#### 1. Configure the service
To define the service, use the ``mongodb`` type:
```yaml {configFile="app"}
services:
# The name of the service container. Must be unique within a project.
:
type: mongodb:
```
Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service.
#### 2. Define the relationship
To define the relationship, use the following configuration:
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<SERVICE_NAME>:
You can define <SERVICE_NAME> as you like, so long as it’s unique between all defined services
and matches in both the application and services configuration.
The example above leverages default endpoint configuration for relationships.
That is, it uses default endpoints behind-the-scenes, providing a relationship
(the network address a service is accessible from) that is identical to the name of that service.
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<RELATIONSHIP_NAME>:service:<SERVICE_NAME>endpoint:mongodb
You can define <SERVICE_NAME> and <RELATIONSHIP_NAME> as you like, so long as it’s unique between all defined services and relationships
and matches in both the application and services configuration.
The example above leverages explicit endpoint configuration for relationships.
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# PHP extensions.runtime:extensions:- mongodb# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<SERVICE_NAME>:
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# PHP extensions.runtime:extensions:- mongodb# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<RELATIONSHIP_NAME>:service:<SERVICE_NAME>endpoint:mongodb
applications:# The name of the app container. Must be unique within a project.myapp:# PHP extensions.runtime:extensions:- mongodb# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:mongodb:services:# The name of the service container. Must be unique within a project.mongodb:type:mongodb:4.0.3
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# PHP extensions.runtime:extensions:- mongodb# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:mongodb:service:mongodbendpoint:mongodbservices:# The name of the service container. Must be unique within a project.mongodb:type:mongodb:4.0.3
### Use in app
To use the configured service in your app, add a configuration file similar to the following to your project.
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"# PHP extensions.runtime:extensions:- mongodb[...]# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:mongodb:service:mongodb:type:mongodb-enterprise:7.0
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"# PHP extensions.runtime:extensions:- mongodb[...]# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:mongodb:service:mongodbendpoint:mongodbservice:mongodb:type:mongodb-enterprise:7.0
This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory.
`myapp` has access to the `mongodb` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship)
(as per [default endpoint](/create-apps/app-reference/single-runtime-image#relationships) configuration for relationships).
From this, ``myapp`` can retrieve access credentials to the service through the [relationship environment variables](#relationship-reference).
```bash {location="myapp/.environment"}
# Set environment variables for individual credentials.
# For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables.
export DB_CONNECTION=="${MONGODB_SCHEME}"
export DB_USERNAME="${MONGODB_USERNAME}"
export DB_PASSWORD="${MONGODB_PASSWORD}"
export DB_HOST="${MONGODB_HOST}"
export DB_PORT="${MONGODB_PORT}"
export DB_DATABASE="${MONGODB_PATH}"
# Surface connection string variable for use in app.
export DATABASE_URL="${DB_CONNECTION}://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_DATABASE}"
```
The above file — ``.environment`` in the ``myapp`` directory — is automatically sourced by Upsun into the runtime environment, so that the variable ``DATABASE_URL`` can be used within the application to connect to the service.
Note that ``DATABASE_URL``, and all Upsun [service environment variables](/development/variables/_index.md#service-environment-variables) like ``MONGODB_HOST``, are environment-dependent.
Unlike the build produced for a given commit,
they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment.
A file very similar to this is generated automatically for your when using the ``upsun ify`` command to [migrate a codebase to Upsun](/get-started/_index.md).
## Access the service directly
You can access MongoDB from you app container via [SSH](../development/ssh/_index.md).
Get the `host` from your [relationship](#relationship-reference).
Then run the following command:
```bash
mongo MONGODB_HOST
```
With the example value, that would be the following:
```bash
mongo mongodb.internal
```
You can obtain the complete list of available service environment variables in your app container by running ``upsun ssh env``.
Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the [service environment variables](/development/variables/_index.md#service-environment-variables) directly rather than hard coding any values.
## Exporting data
The most straightforward way to export data from a MongoDB database is to open an SSH tunnel to it
and export the data directly using MongoDB's tools.
First, open an SSH tunnel with the Upsun CLI:
```bash
upsun tunnel:open
```
That opens an SSH tunnel to all services on your current environment and produce output like the following:
```bash
SSH tunnel opened on port 30000 to relationship: mongodb
```
The port may vary in your case.
You also need to obtain the user, password, and database name from the relationships array, as above.
Then, connect to that port locally using `mongodump` (or your favorite MongoDB tools) to export all data in that server:
```bash
mongodump --port 30000 -u main -p main --authenticationDatabase main --db main
```
(If necessary, vary the `-u`, `-p`, `--authenticationDatabase` and `--db` flags.)
As with any other shell command it can be piped to another command to compress the output or redirect it to a specific file.
For further references, see the [official `mongodump` documentation](https://docs.mongodb.com/database-tools/mongodump/).
## Upgrading
To upgrade to 6.0 from a version earlier than 5.0, you must successively upgrade major releases until you have upgraded to 5.0.
For example, if you are running a 4.2 image, you must upgrade first to 4.4 and then upgrade to 5.0 before you can upgrade to 6.0.
For more details on upgrading and how to handle potential application backward compatibility issues,
see the [MongoDB release notes](https://docs.mongodb.com/manual/release-notes).
Note
Make sure you first test your migration on a separate branch.
Also, be sure to take a backup of your production environment before you merge this change.
Downgrading isn't supported. If you want, for whatever reason, to downgrade you should create a mongodump, remove the service, recreate the service, and import your dump.
# Add services [Network Storage](https://docs.upsun.com/add-services/network-storage.html)
The Network Storage service enables a new kind of [mount](../create-apps/app-reference/single-runtime-image.md#mounts)
that refers to a shared service rather than to a local directory.
This service allows you to store data and share it between different apps.
## Supported versions
You can select the major and minor version.
Patch versions are applied periodically for bug fixes and the like.
When you deploy your app, you always get the latest available patches.
2.0
This service is the Upsun network storage implementation, not the version of a third-party application.
Note
It isn’t possible to upgrade or downgrade the network storage service version while keeping existing data in place.
Changing the service version requires that the service be reinitialized.
Any change to the service version results in existing data becoming inaccessible.
### Deprecated versions
The following versions are [deprecated](/glossary.html#deprecated-versions).
They're available, but they aren't receiving security updates from upstream and aren't guaranteed to work.
They'll be removed in the future,
so migrate to one of the [supported versions](#supported-versions).
1.0
## Usage example
### 1. Configure the service
To define the service, use the ``network-storage`` type:
```yaml {configFile="app"}
services:
# The name of the service container. Must be unique within a project.
:
type: network-storage:
```
`` must be [RFC 1123](https://tools.ietf.org/html/rfc1123) compliant, and as such it must:
- Contain at most 63 characters
- Contain only lowercase alphanumeric characters or `-` (underscores `_` are not allowed)
- Start with an alphanumeric character
- End with an alphanumeric character
This is due to the fact that `` is used as hostname for the network storage.
Note that changing the name of the service replaces it with a brand new service and all existing data is lost.
Back up your data before changing the service.
### 2. Add the mount
To define the mount accessible by your application, use the following configuration:
```yaml {configFile="app"}
applications:
# The name of the app container. Must be unique within a project.
:
mounts:
:
source: service
service:
source_path:
services:
# The name of the service container. Must be unique within a project.
:
type: network-storage:
```
- `` is the path to your mount within the app container (relative to the app’s root).
- `` is the name you [defined in step 1](#1-configure-the-service).
- `` specifies where the mount points inside the service.
If the `source_path` is an empty string (`""`), your mount points to the entire service.
If you don’t define a `source_path`, Upsun uses the `MOUNT_PATH` as default value, without leading or trailing slashes.
For example, if your mount lives in the `/my/files/` directory within your app container, it will point to a `my/files` directory within the service.
### Example configuration
```yaml {configFile="services"}
applications:
# The name of the app container. Must be unique within a project.
myapp:
mounts:
'my/files':
source: service
service: network-storage
source_path: files
services:
# The name of the service container. Must be unique within a project.
network-storage:
type: network-storage:2.0
```
## Multi-application usage
If your project contains [multiple apps](../create-apps/multi-app/_index.md),
they may [share `storage` mounts](/create-apps/app-reference/single-runtime-image#share-a-mount-between-several-apps).
Alternatively, they may use shared `service` mounts.
If the `source_path` is the same for both apps,
the files are shared between the two applications even if the mount location is different.
It's also possible to have one app mount a `source_path` that's a subdirectory of another application's mount.
For example:
```yaml {configFile="apps"}
applications:
# The name of the app container. Must be unique within a project.
app1:
# The location of the application's code.
source:
root: "app1"
[...]
mounts:
# The path to your mount within the app container (relative to the app's root).
'web/uploads':
# Specifies that the mount points to a network storage service that can be shared between apps.
source: service
# The name of the network storage service the mount points to.
service: network-storage
# Specifies where your mount points inside the external directory that is mounted to your app container.
source_path: uploads
# The name of the app container. Must be unique within a project.
app2:
# The location of the application's code.
source:
root: "app2"
[...]
mounts:
# The path to your mount within the app container (relative to the app's root).
'process':
# Specifies that the mount points to a network storage service that can be shared between apps.
source: service
# The name of the network storage service the mount points to.
service: network-storage
# Specifies where your mount points inside the external directory that is mounted to your app container.
# Since the target is the uploads directory app1's mount already points to,
# the network storage service is effectively shared between app1 and app2.
source_path: uploads/incoming
# The path to your mount within the app container (relative to the app's root).
'done':
# Specifies that the mount points to a network storage service that can be shared between apps.
source: service
# The name of the network storage service the mount points to.
service: network-storage
# Specifies where your mount points inside the external directory that is mounted to your app container.
# Since the target is the uploads directory app1's mount already points to,
# the network storage service is effectively shared between app1 and app2.
source_path: uploads/done
```
In this example, `app1` has access to the entire `uploads` directory by writing to `web/uploads`.
`app2` has two mounts that it can write to: `process` and `done`.
The `process` mount refers to the same directory as the `web/uploads/incoming` directory does on `app1`,
and the `done` mount refers to the same directory as the `web/uploads/done` directory on `app1`.
## How do I give my workers access to my main application’s files?
If you need to use a worker with access to the same file mount as your web-serving app,
define all the necessary mounts as `service` mounts.
The following example assumes a Network Storage service named `files` has been defined in `.upsun/config.yaml`.
Drupal files directories are shared between the `web` and `worker` instances,
while the Drush backup directory is unique to the `web` instance.
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: "php:8.4"
[...]
mounts:
# The public and private files directories are
# network mounts shared by web and workers.
'web/sites/default/files':
source: service
service: files
source_path: files
'private':
source: service
service: files
source_path: private
# The backup, temp, and cache directories for
# Drupal's CLI tools don't need to be shared between web and workers.
# It wouldn't hurt anything to make them network
# shares, however.
'/.drush':
source: storage
source_path: drush
'tmp':
source: tmp
source_path: tmp
'drush-backups':
source: storage
source_path: drush-backups
'/.console':
source: storage
source_path: console
# Crons run on the web container, so they have the
# same mounts as the web container.
crons:
drupal:
spec: '*/20 * * * *'
commands:
start: 'cd web ; drush core-cron'
# The worker defined here also has the same 6 mounts;
# 2 of them are shared with the web container,
# the other 4 are local to the worker.
workers:
queue:
commands:
start: |
cd web && drush queue-run myqueue
```
## How can I migrate data from a `storage` mount to a `service` mount?
Network Storage `service` mounts can be shared between different apps,
while `storage` mounts can only be shared between different _instances_ of the same app.
To move data from a `storage` mount to a `service` one, follow these instructions.
Assuming you have the following `storage` mount:
```yaml {configFile="app"}
applications:
myapp:
[...]
mounts:
web/uploads:
source: storage
source_path: uploads
```
1. Add a new `network-storage` service to your configuration:
```yaml {configFile="app"}
applications:
myapp:
[...]
mounts:
web/uploads:
source: storage
source_path: uploads
services:
# The name of the service container. Must be unique within a project.
network-storage:
type: network-storage:2.0
```
Note
Make sure you allocate enough disk space to your network-storage service
for your existing files with some buffer.
2. Add a new `service` mount, named `new-uploads`:
```yaml {configFile="services"}
applications:
myapp:
[...]
mounts:
web/uploads:
source: storage
source_path: uploads
new-uploads:
source: service
service: network-storage
source_path: uploads
services:
# The name of the service container. Must be unique within a project.
network-storage:
type: network-storage:2.0
```
Note that each mount is on a different storage service, which is why they can have the same `source_path`.
3. Deploy your changes.
4. Copy all your files from the `storage` (`web/uploads`) mount to the `service` (`new-uploads`) mount using `rsync`:
```bash
rsync -avz web/uploads/* new-uploads/
```
5. Reverse the mounts.
To do so, rename the `storage` mount to `old-uploads`, and point the `web/uploads` directory to the `service` mount:
```yaml {configFile="services"}
applications:
myapp:
[...]
mounts:
old-uploads:
source: storage
source_path: uploads
web/uploads:
source: service
service: network-storage
source_path: uploads
services:
# The name of the service container. Must be unique within a project.
network-storage:
type: network-storage:2.0
```
6. Push your changes and check that the files are now accessible from the `service` mount (now named `web/uploads`).
To check that no files were lost during the transfer, run the following command:
```bash
rsync -avz old-uploads/* web/uploads/
```
7. Delete the contents of the `old-uploads` `storage` mount before removing it.
8. Push your changes again.
# Add services [OpenSearch (search service)](https://docs.upsun.com/add-services/opensearch.html)
OpenSearch is a distributed RESTful search engine built for the cloud.
See the [OpenSearch documentation](https://opensearch.org/docs/latest/) for more information.
To switch from Elasticsearch, follow the same procedure as for [upgrading](#upgrading).
## Supported versions
In the list below, notice that there you only specify the major version.
Each version represents a rolling release of the latest minor version available from the upstream.
The latest compatible minor version and patches are applied automatically.
2
1
You can see the latest minor and patch versions of OpenSearch available from the [`2.x`](https://opensearch.org/lines/2x.html) and [`1.x`](https://opensearch.org/lines/1x.html) (1.3) release lines.
## Deprecated versions
The following versions are still available in your projects,
but they're at their end of life and are no longer receiving security updates from upstream,
or are no longer the recommended way to configure the service on Upsun.
1.2
1.1
To ensure your project remains stable in the future,
switch to [a supported version](#supported-versions).
## Relationship reference
For each service [defined via a relationship](#usage-example) to your application,
Upsun automatically generates corresponding environment variables within your application container,
in the ``$_`` format.
Here is example information available through the [service environment variables](/development/variables/_index.md#service-environment-variables) themselves,
or through the [``PLATFORM_RELATIONSHIPS`` environment variable](/development/variables/use-variables.md#use-provided-variables).
You can obtain the complete list of available service environment variables in your app container by running upsun ssh env.
Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the service environment variables directly rather than hard coding any values.
For some advanced use cases, you can use the PLATFORM_RELATIONSHIPS environment variable.
The structure of the PLATFORM_RELATIONSHIPS environment variable can be obtained by running upsun relationships in your terminal:
# Decode the built-in credentials object variable.exportRELATIONSHIPS_JSON=$(echo$PLATFORM_RELATIONSHIPS| base64 --decode)# Set environment variables for individual credentials.exportAPP_OPENSEARCH_HOST="$(echo$RELATIONSHIPS_JSON| jq -r '.opensearch[0].host')"
## Usage example
### 1. Configure the service
To define the service, use the ``opensearch`` type:
```yaml {configFile="app"}
services:
# The name of the service container. Must be unique within a project.
:
type: opensearch:
```
Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service.
### 2. Define the relationship
To define the relationship, use the following configuration:
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<SERVICE_NAME>:
You can define <SERVICE_NAME> as you like, so long as it’s unique between all defined services
and matches in both the application and services configuration.
The example above leverages default endpoint configuration for relationships.
That is, it uses default endpoints behind-the-scenes, providing a relationship
(the network address a service is accessible from) that is identical to the name of that service.
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<RELATIONSHIP_NAME>:service:<SERVICE_NAME>endpoint:opensearch
You can define <SERVICE_NAME> and <RELATIONSHIP_NAME> as you like, so long as it’s unique between all defined services and relationships
and matches in both the application and services configuration.
The example above leverages explicit endpoint configuration for relationships.
applications:# The name of the app container. Must be unique within a project.myapp:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:opensearch:services:# The name of the service container. Must be unique within a project.opensearch:type:opensearch:2
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:opensearch:service:opensearchendpoint:opensearchservices:# The name of the service container. Must be unique within a project.opensearch:type:opensearch:2
### Use in app
To use the configured service in your app, add a configuration file similar to the following to your project.
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"[...]# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:opensearch:services:# The name of the service container. Must be unique within a project.opensearch:type:opensearch:2
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"[...]# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:opensearch:service:opensearchendpoint:opensearchservices:# The name of the service container. Must be unique within a project.opensearch:type:opensearch:2
This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory.
`myapp` has access to the `opensearch` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship)
(as per [default endpoint](/create-apps/app-reference/single-runtime-image#relationships) configuration for relationships).
From this, ``myapp`` can retrieve access credentials to the service through the [relationship environment variables](#relationship-reference).
```bash {location="myapp/.environment"}
# Set environment variables for individual credentials.
# For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables.
export OS_SCHEME=${OPENSEARCH_SCHEME}
export OS_HOST=${OPENSEARCH_HOST}
export OS_PORT=${OPENSEARCH_PORT}
# Surface more common OpenSearch connection string variables for use in app.
export OS_USERNAME=${OPENSEARCH_USERNAME}
export OS_PASSWORD=${OPENSEARCH_PASSWORD}
export OPENSEARCH_HOSTS=[\"$OS_SCHEME://$OS_HOST:$OS_PORT\"]
```
The above file — ``.environment`` in the ``myapp`` directory — is automatically sourced by Upsun into the runtime environment, so that the variable ``OPENSEARCH_HOSTS`` can be used within the application to connect to the service.
Note that ``OPENSEARCH_HOSTS``, and all Upsun [service environment variables](/development/variables/_index.md#service-environment-variables) like ``OPENSEARCH_HOST``, are environment-dependent.
Unlike the build produced for a given commit,
they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment.
A file very similar to this is generated automatically for your when using the ``upsun ify`` command to [migrate a codebase to Upsun](/get-started/_index.md).
Note
When you create an index on OpenSearch,
don’t specify the number_of_shards or number_of_replicas settings in your OpenSearch API call.
These values are set automatically based on available resources.
## Authentication
By default, OpenSearch has no authentication.
No username or password is required to connect to it.
You may optionally enable HTTP Basic authentication.
To do so, include the following in your `.upsun/config.yaml` configuration:
```yaml {configFile="services"}
services:
# The name of the service container. Must be unique within a project.
opensearch:
type: opensearch:2
configuration:
authentication:
enabled: true
```
That enables mandatory HTTP Basic auth on all requests.
The credentials are available in any relationships that point at that service,
in the `OPENSEARCH_USERNAME` and `OPENSEARCH_PASSWORD` [service environment variables](/development/variables/_index.md#service-environment-variables).
You can obtain the complete list of available service environment variables in your app container by running ``upsun ssh env``.
Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the [service environment variables](/development/variables/_index.md#service-environment-variables) directly rather than hard coding any values.
This functionality is generally not required if OpenSearch isn't exposed on its own public HTTP route.
However, certain applications may require it, or it allows you to safely expose OpenSearch directly to the web.
To do so, add a route to `.upsun/config.yaml` that has `opensearch:opensearch` as its upstream
(where `opensearch` is whatever you named the service).
For example:
```yaml {configFile="routes"}
routes:
"https://www.os.{default}/":
type: redirect
to: "https://os.{default}/"
"https://os.{default}/":
type: upstream
upstream: "opensearch:opensearch"
services:
# The name of the service container. Must be unique within a project.
opensearch:
configuration:
authentication:
enabled: true
```
## Plugins
OpenSearch offers a number of plugins.
To enable them, list them under the `configuration.plugins` key in your `.upsun/config.yaml` file, like so:
```yaml {configFile="services"}
services:
# The name of the service container. Must be unique within a project.
opensearch:
configuration:
plugins:
- analysis-icu
```
In this example you'd have the ICU analysis plugin and the size mapper plugin.
If there is a publicly available plugin you need that isn't listed here, [contact support](/learn/overview/get-support.md).
### Available plugins
This is the complete list of plugins that can be enabled:
| Plugin | Description | 1 | 2 |
|-------------------------|-------------------------------------------------------------------------------------------|-----|---|
| `analysis-icu` | Support ICU Unicode text analysis | * | * |
| `analysis-kuromoji` | Japanese language support | * | * |
| `analysis-nori` | Integrates Lucene Nori analysis module into OpenSearch | * | * |
| `analysis-phonetic` | Phonetic analysis | * | * |
| `analysis-smartcn` | Smart Chinese Analysis Plugins | * | * |
| `analysis-stempel` | Stempel Polish Analysis Plugin | * | * |
| `analysis-ukrainian` | Ukrainian language support | * | * |
| `ingest-attachment` | Extract file attachments in common formats (such as PPT, XLS, and PDF) | * | * |
| `mapper-annotated-text` | Adds support for text fields with markup used to inject annotation tokens into the index | * | * |
| `mapper-murmur3` | Murmur3 mapper plugin for computing hashes at index-time | * | * |
| `mapper-size` | Size mapper plugin, enables the `_size` meta field | * | * |
| `repository-s3` | Support for using S3 as a repository for Snapshot/Restore | * | * |
| `transport-nio` | Support for NIO transport | * | * |
### Plugin removal
Removing plugins previously added in your `.upsun/config.yaml` file doesn't automatically uninstall them from your OpenSearch instances.
This is deliberate, as removing a plugin may result in data loss or corruption of existing data that relied on that plugin.
Removing a plugin usually requires reindexing.
To permanently remove a previously enabled plugin,
[upgrade the service](#upgrading) to create a new instance of OpenSearch and migrate to it.
In most cases it isn't necessary as an unused plugin has no appreciable impact on the server.
## Upgrading
The OpenSearch data format sometimes changes between versions in incompatible ways.
OpenSearch doesn't include a data upgrade mechanism as it's expected that all indexes can be regenerated from stable data if needed.
To upgrade (or downgrade) OpenSearch, use a new service from scratch.
There are two ways to do so.
### Destructive
In your `.upsun/config.yaml` file, change the version *and* name of your OpenSearch service.
Be sure to also update the reference to the now changed service name in it's corresponding application's `relationship` block.
When you push that to Upsun, the old service is deleted and a new one with the new name is created with no data.
You can then have your application reindex data as appropriate.
This approach has the downsides of temporarily having an empty OpenSearch instance,
which your application may or may not handle gracefully, and needing to rebuild your index afterward.
Depending on the size of your data that could take a while.
### Transitional
With a transitional approach, you temporarily have two OpenSearch services.
Add a second OpenSearch service with the new version a new name and give it a new relationship in `.upsun/config.yaml`.
You can optionally run in that configuration for a while to allow your application to populate indexes in the new service as well.
Once you're ready to switch over, remove the old OpenSearch service and relationship.
You may optionally have the new OpenSearch service use the old relationship name if that's easier for your app to handle.
Your application is now using the new OpenSearch service.
This approach has the benefit of never being without a working OpenSearch instance.
On the downside, it requires two running OpenSearch servers temporarily,
each of which consumes resources and needs adequate disk space.
Depending on the size of your data, that may be a lot of disk space.
# Activity scripts [Activity reference](https://docs.upsun.com/integrations/activity/reference.html)
Activities log changes to your project,
including when you deploy your app,
when you [push code](#push), and when a [cron job is run](#cron).
To automate your workflows, you can parse and react to the activity's JSON object
through [activity scripts](../activity/_index.md).
## Activity schema
Every activity has a corresponding JSON object containing all information for that activity,
including timestamps, configuration, and sometimes logs.
In practice, you can ignore much of the JSON object's content.
The most commonly used values are documented in this reference.
The response differs depending on the activity and doesn't always include all fields.
### Example response
The following is a shortened example of a response for an [environment sync activity](/glossary.md#sync).
You can also see [complete examples of responses](#examples).
``` json
{
"id": "abcdefg123456",
...
"created_at": "2022-12-16T14:28:17.890467+00:00",
"updated_at": null,
"type": "environment.synchronize",
"parameters": {
...
},
"project": "abcdefgh1234567",
"environments": [
"feature"
],
"state": "complete",
"result": "success",
"started_at": "2022-12-16T14:28:18.188888+00:00",
"completed_at": "2022-12-16T14:31:48.809068+00:00",
"completion_percent": 100,
"cancelled_at": null,
"timings": {
"wait": 0,
"build": 0.349,
"deploy": 209.986,
"execute": 210.508
},
"log": "Building application 'app' (runtime type: php:8.2, tree: 9851a01)\n Reusing existing build for this tree ID\n\n...\nRedeploying environment test, as a clone of main\n ...\n Closing all services\n Opening application app and its relationships\n Executing deploy hook for application app\n ... Environment configuration\n app (type: php:8.0, size: S, disk: 2048)\n\n ...",
"payload": {
...
},
"description": "Cloé Weber synchronized test's data from Main",
"text": "Cloé Weber synchronized test's **data** from Main",
"expires_at": "2023-12-16T14:28:17.890467+00:00"
}
```
### `id`
A unique `id` value to identify the activity itself.
### `*_at`
`created_at`, `started_at`, `updated_at`, `cancelled_at`, `completed_at`, and `expires_at` are all timestamps in UTC.
For when a given activity occurred, use `completed_at`.
You can use these properties to calculate the duration of the activity.
To calculate the timing for steps in the activity, see the [`timings` property](#timings).
### `parameters`
The `parameters` property includes detailed information about what triggered the activity,
such as the user, the impacted environment, the git commits, or the cron commands.
The response changes based on the activity.
### `project`
The ID of the project in which the activity took place.
Use this value to distinguish multiple projects sent the same URL.
Different from [`project` activities](#type).
### `type`
The type of the activity in one of the following categories:
- [Project](#project-activity-types)
- [Environment](#environment-activity-types)
- [Integration](#integration-activity-types)
- [Maintenance](#maintenance-activity-types)
#### `project` activity types
Activities that happened on a given project.
The following table presents the possible activity types:
| Name | Description |
|-----------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `project.clear_build_cache` | The build cache is cleared. |
| `project.create` | A new project is created. |
| `project.domain.create` | A new [domain](administration/web/configure-project.md#domains) has been added to the project. |
| `project.domain.delete` | An existing [domain](administration/web/configure-project.md#domains) has been deleted from the project. |
| `project.domain.update` | An existing [domain](administration/web/configure-project.md#domains) has been updated from the project. |
| `project.metrics.enable` | A metric from the [continuous profiling](/increase-observability.md) has been enabled. |
| `project.metrics.update` | A metric from the [continuous profiling](/increase-observability.md) has been updated. |
| `project.metrics.disable` | A metric from the [continuous profiling](/increase-observability.md) has been disabled. |
| `project.modify.title` | The project title has changed. |
| `project.variable.create` | A new [project variable](/administration/web/configure-project.md#variables) has been created. The value is visible only if the variable is not [set as sensitive](../../development/variables/set-variables.md#variable-options). |
| `project.variable.delete` | A [project variable](/administration/web/configure-project.md#variables) has been deleted. |
| `project.variable.update` | A [project variable](/administration/web/configure-project.md#variables) has been modified. |
#### `environment` activity types
Activities that happened on an environment.
The following table presents the possible activity types:
| Name | Description |
|--------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `environment.activate` | The environment has been made [active](/glossary.md#active-environment). |
| `environment.backup` | A user triggered a [backup](/environments/backup.md). |
| `environment.backup.delete` | A user deleted a [backup](/environments/backup.md). |
| `environment.branch` | A [new branch](/environments.md#create-environments) has been created via the CLI, Console, or API. A branch created via Git shows up as `environment.push`. |
| `environment.certificate.renewal` | An environment's SSL certificate has been [renewed](/define-routes/https.md#certificate-renewals). |
| `environment.cron` | A [cron job](/create-apps/app-reference/single-runtime-image.md#crons) has completed. |
| `environment.deactivate` | An environment has been made [inactive](/glossary.md#inactive-environment). |
| `environment.delete` | An environment's code was deleted through Git. |
| `environment.domain.create` | A new [domain](administration/web/configure-project.md#domains) has been associated with the environment. |
| `environment.domain.delete` | A [domain](administration/web/configure-project.md#domains) associated with the environment has been removed. |
| `environment.domain.update` | A [domain](administration/web/configure-project.md#domains) associated with the environment has been updated, such as having its SSL certificate modified. |
| `environment.initialize` | The [default branch](/environments.md#default-environment) of the project has just been initialized with its first commit. |
| `environment.merge` | An environment was [merged](/glossary.md#merge) through the CLI, Console, or API. A basic Git merge doesn't trigger this activity. |
| `environment.merge-pr` | A Pull Request/Merge Request was merged through the CLI, Console, or API. A basic Git merge doesn't trigger this activity. |
| `environment.operation` | A [source operation](/create-apps/runtime-operations.md) has been triggered |
| `environment.pause` | An environment has been [paused](/environments.md#pause-an-environment). |
| `environment.push` | A user [pushed](/administration/cli/reference.md#environmentpush) code to a branch, either existing or new. |
| `environment.redeploy` | An environment was [redeployed](/administration/cli/reference.md#environmentredeploy). |
| `environment.restore` | A user restored a [backup](/environments/backup.md). |
| `environment.resume` | An inactive environment was [resumed](/environments.md#resume-a-paused-environment) |
| `environment.resources.update` | The resources allocated to the environment [have been updated](/manage-resources/adjust-resources.md). |
| `environment.route.create` | A new [route](/administration/web/configure-environment.md#routes) has been created through the API. Edits made using Git to the `.upsun/config.yaml` file don't trigger this activity. |
| `environment.route.delete` | A [route](/administration/web/configure-environment.md#routes) has been deleted through the API. Edits made using Git to the `.upsun/config.yaml` file don't trigger this activity. |
| `environment.route.update` | A [route](/administration/web/configure-environment.md#routes) has been modified through the API. Edits made using Git to the `.upsun/config.yaml` file don't trigger this activity. |
| `environment.source-operation` | A [source operation](/create-apps/source-operations.md) has been triggered. |
| `environment.synchronize` | An environment has had its data and/or code replaced with the data and/or code from its parent environment. |
| `environment.update.http_access` | [HTTP access rules](/administration/web/configure-environment.md#http-access-control) for an environment have been modified. |
| `environment.update.restrict_robots` | The option to [hide from search engines](../../environments/search-engine-visibility.md) has been enabled or disabled for an environment. |
| `environment.update.smtp` | Email sending has been enabled or disabled for an environment. |
| `environment.variable.create` | A [new variable](/development/variables/set-variables.md#variable-options) has been created. The value is visible only if the variable is not [set as sensitive](../../development/variables/set-variables.md#variable-options). |
| `environment.variable.delete` | A [variable](/development/variables/set-variables.md#variable-options) has been deleted. |
| `environment.variable.update` | A [variable](/development/variables/set-variables.md#variable-options) has been modified. |
| `environment_type.access.create` | A [new access](/administration/users.md#manage-project-access) has been added to the environment |
| `environment_type.access.delete` | An [existing access](/administration/users.md#manage-project-access) to the environment has been deleted |
| `environment_type.access.update` | An [existing access](/administration/users.md#manage-project-access) to the environment has been updated |
#### `integration` activity types
Activities that relate to an integration.
The following table presents the possible activity types:
| Name | Description |
|-----------------------------------------------|-----------------------------------------------------------------------------------------------------------------------|
| `integration.bitbucket.fetch` | A fetch has been triggered on your [Bitbucket Cloud](/integrations/source/bitbucket.md#bitbucket-cloud) repository. |
| `integration.bitbucket.register_hooks` | An integration hook has been registered with [Bitbucket Cloud](/integrations/source/bitbucket.md#bitbucket-cloud). |
| `integration.bitbucket_server.fetch` | A fetch has been triggered on your [Bitbucket Server](/integrations/source/bitbucket.md#bitbucket-server) repository. |
| `integration.bitbucket_server.register_hooks` | An integration hook has been registered with [Bitbucket Server](/integrations/source/bitbucket.md#bitbucket-server). |
| `integration.github.fetch` | A fetch has been triggered on your [GitHub](/integrations/source/github.md) repository. |
| `integration.gitlab.fetch` | A fetch has been triggered on your [GitLab](/integrations/source/gitlab.md) repository. |
| `integration.health.email` | A [health notification](../notifications.md) was sent by email. |
| `integration.health.pagerduty` | A [health notification](../notifications.md) was sent to PagerDuty. |
| `integration.health.slack` | A [health notification](../notifications.md) was sent to Slack. |
| `integration.health.webhook` | A [health notification](../notifications.md) was sent to a webhook. |
| `integration.script` | An [activity script](/integrations/activity/_index.md) has been triggered. |
| `integration.webhook` | A [webhook](/integrations/activity/webhooks.md) was triggered. |
#### `maintenance` activity types
Activities that relate to a maintenance.
The following table presents the possible types:
| Name | Description |
|-----------------------|-----------------------------------------------------------|
| `maintenance.upgrade` | An upgrade is triggered for API Server and Metrics Server |
### `environments`
An array listing the environments that were involved in the activity.
It's usually only a single value representing one environment.
### `state`
The current state of the activity.
Its value can be `pending`, `in_progress`, `complete`, `cancelled`, or `scheduled`.
### `completion_percent`
What percentage of the activity is complete.
### `result`
Whether or not the activity completed successfully.
If it did, the value is `success`.
Note that certain activities, such as deploy hooks,
can be marked as successful activities even if some commands failed.
### `timings`
The amount of time required by the activity.
It can include the following properties:
| Name | Description |
|-----------|--------------------------------------------------------------|
| `wait` | The delay if a command is set to wait before being executed. |
| `build` | The execution time for the build hook. |
| `deploy` | The execution time for the deploy hook. |
| `execute` | The execution time for your script or cron job. |
### `log`
A human-friendly record of what happened in the activity.
The log shouldn't be parsed for data as its structure isn't guaranteed.
### `description`
A short machine-readable description of the activity.
### `text`
A short human-readable description of the activity.
### `payload`
Contains settings and details related to the completed activity.
Its content varies based on the activity type.
| Name | Description |
|-------------------------|---------------------------------------------------------------------------------------------------------------------------------|
| `payload.user` | The user that triggered the activity. For details on its properties, see the [`user` payload](#user-payload). |
| `payload.environment` | The environment affected by the activity. For details on its properties, see the [`environment` payload](#environment-payload). |
| `payload.commits` | A list of changes with their Git metadata. |
| `payload.commits_count` | The number of Git commits. |
| `payload.deployment` | Information about the deployed environment. For details on its properties, see the [`deployment` payload](#deployment-payload). |
| `payload.project` | Information about the project. For details on its properties, see the [`project` payload](#project-payload). |
#### `user` payload
Contains information about the Upsun user that triggered the activity.
| Name | Description |
|-----------------------------|---------------------------------------------|
| `payload.user.created_at` | The date the user was created. |
| `payload.user.display_name` | The user's name in a human-friendly format. |
| `payload.user.id` | The user's ID. |
| `payload.user.updated_at` | The date the user was last updated. |
#### `environment` payload
Contains information about the environment associated with the activity,
including its settings, state, and deployment.
The following table presents the most notable properties of the environment:
| Name | Description |
|-------------------------------------|---------------------------------------------------------------------------------------------|
| `payload.environment.name` | The environment name. |
| `payload.environment.type` | The [environment type](../../administration/users.md#environment-type-roles). |
| `payload.environment.head_commit` | The ID of the environment's latest Git commit. |
| `payload.environment.edge_hostname` | The URL you should target when setting up a [custom domain](../../domains/steps/_index.md). |
Different from [`environment` activities](#type).
#### `project` payload
Contains information about the project associated with the activity,
including plan details, timezone, and region.
The following table presents the most notable properties of the project:
| Name | Description |
|--------------------------------|-----------------------------------------------------------------------------------------|
| `payload.project.timezone` | Your project's [timezone](../../projects/change-project-timezone.md). |
| `payload.project.region` | Your project's [region](../../development/regions.md#regions). |
| `payload.project.title` | Your project's name. |
| `payload.project.subscription` | All of the details about your project's [plan](../../administration/pricing/_index.md). |
Different from [`project` activities](#type).
#### `deployment` payload
Contains information about the deployed environment, if one is associated with the activity.
The following table presents the most notable properties of the deployment:
| Name | Description |
|--------------------------------|----------------------------------------------------------------------------------------------------------------------------------------|
| `payload.deployment.routes` | All the URLs connected to the environment. The list includes redirects. To exclude redirects, find objects whose `type` is `upstream`. |
| `payload.deployment.services` | All the services on your environment. |
| `payload.deployment.variables` | All the [variables for the environment](../../development/variables/_index.md). |
The `payload.deployment` property includes the configuration extracted from the following sources:
- Your [app configuration](../../create-apps/_index.md)
- Your [routes](../../define-routes/_index.md)
- Your [services](../../add-services/_index.md)
## Maximum activities and parallelism
Project activities are distributed across separate queues,
which enables *two* simultaneous activities to occur in parallel across your environments.
For a given environment, only one activity can run at a time.
Those queues include the following types of activities:
| Name | Description |
|----------------|------------------------------------------------------------------------------------------------------|
| `default` | The most common activities on repositories (pushes, merges) and environments (syncs, redeployments). |
| `integrations` | Source and webhook integration activities. |
| `backup` | Backup activities. |
| `cron` | Cron activities. |
Production activities are prioritized across all queues.
When an activity for the production environment is triggered, it's placed at the top of the queue.
This makes it unlikely that activities on preview environments block activities for the production environment for long,
though there may be a temporary wait.
## Examples
The response is often usually long, so the following examples are shortened using ellipses.
Remember that the response differs depending on the activity and not all fields are always available.
To test responses, [set up a webhook](./webhooks.md#setup).
### Cron
When a cron job is triggered, the activity contains all the [job's information](/create-apps/app-reference/single-runtime-image.md#crons).
The following example response was triggered by a setting
where the cron is scheduled to run every five minutes (`5 * * * *`)
with the command `sleep 60 && echo sleep-60-finished && date` and times out after 86,400 seconds.
To get details about the configured cron job, see the `parameters` property:
``` json
...
"parameters": {
"user": "admin",
"cluster": "abcdefgh1234567-main-abcd123",
"environment": "main",
"application": "app",
"cron": "saybye",
"spec": {
"spec": "5 * * * *",
"commands": {
"start": "sleep 60 && echo sleep-60-finished && date",
"stop": null
},
"shutdown_timeout": null,
"timeout": 86400
}
...
```
The following example shows the full activity response to a cron job:
``` json
{
"id": "ypalrypnezbye",
"_links": {
"self": {
"href": "https://eu-3.upsun.com/api/projects/abcdefgh1234567/activities/ypalrypnezbye"
},
"log": {
"href": "/api/projects/abcdefgh1234567/activities/ypalrypnezbye/log"
}
},
"created_at": "2022-12-13T16:06:08.081312+00:00",
"updated_at": null,
"type": "environment.cron",
"parameters": {
"user": "admin",
"cluster": "abcdefgh1234567-main-abcd123",
"environment": "main",
"application": "app",
"cron": "saybye",
"spec": {
"spec": "5 * * * *",
"commands": {
"start": "sleep 60 && echo sleep-60-finished && date",
"stop": null
},
"shutdown_timeout": null,
"timeout": 86400
}
},
"project": "abcdefgh1234567",
"environments": [
"main"
],
"state": "complete",
"result": "success",
"started_at": "2022-12-13T16:06:08.258090+00:00",
"completed_at": "2022-12-13T16:07:09.658339+00:00",
"completion_percent": 100,
"cancelled_at": null,
"timings": {
"wait": 0,
"execute": 61.244
},
"log": "hello world\nTue Dec 13 16:07:09 UTC 2022",
"payload": {
"user": {
"id": "admin",
"created_at": "2022-12-13T16:06:08.066085+00:00",
"updated_at": null,
"display_name": "Upsun Bot"
},
"project": {
"id": "abcdefgh1234567",
"created_at": "2022-03-22T15:47:28.739099+00:00",
"updated_at": "2022-12-01T09:42:19.860188+00:00",
"attributes": {},
"title": "php-test",
"description": "",
"owner": "c9926428-44dc-4b10-be03-a26dd43b44c1",
"namespace": "upsun",
"organization": "01FF4NBNVMMDWP1NVK0G4EGJW0",
"default_branch": "main",
"status": {
"code": "provisioned",
"message": "ok"
},
"timezone": "Europe/Dublin",
"region": "eu-3.upsun.com",
"repository": {
"url": "abcdefgh1234567@git.eu-3.upsun.com:abcdefgh1234567.git",
"client_ssh_key": "ssh-rsa aaaaaaabbbbbbbcccccccddddddd abcdefgh1234567@upsun"
},
"default_domain": null,
"subscription": {
"license_uri": "https://accounts.upsun.com/api/v1/licenses/2291467",
"plan": "development",
"environments": 3,
"storage": 5120,
"included_users": 1,
"subscription_management_uri": "https://console.upsun.com-/users/abcd12345/billing/plan/12345678",
"restricted": false,
"suspended": false,
"user_licenses": 1
}
},
"environment": {
"id": "main",
"created_at": "2022-03-22T15:47:43.750880+00:00",
"updated_at": "2022-11-29T16:16:37.085719+00:00",
"name": "main",
"machine_name": "main-abcd123",
"title": "Main",
"attributes": {},
"type": "production",
"parent": null,
"default_domain": null,
"clone_parent_on_create": true,
"deployment_target": "local",
"is_pr": false,
"status": "active",
"enable_smtp": true,
"restrict_robots": true,
"edge_hostname": "main-abcd123-abcdefgh1234567.eu-3.platformsh.site",
"deployment_state": {
"last_deployment_successful": true,
"last_deployment_at": "2022-11-29T16:16:37.085609+00:00",
"crons": {
"enabled": true,
"status": "running"
}
},
"resources_overrides": {},
"last_active_at": "2022-12-13T15:07:10.862854+00:00",
"last_backup_at": null,
"project": "abcdefgh1234567",
"is_main": true,
"is_dirty": false,
"has_code": true,
"head_commit": "6aac318907b50252976c47e4e62ed95d438af0ea",
"merge_info": {
"commits_ahead": 0,
"commits_behind": 0,
"parent_ref": null
},
"has_deployment": true
},
"cron": "saybye"
},
"description": "Upsun Bot ran cron saybye",
"text": "Upsun Bot ran cron **saybye**",
"expires_at": "2023-01-12T16:06:08.081293+00:00"
}
```
### Push
A push activity contains several properties.
The `commits` property contains everything related to the Git push that triggered the activity:
``` json
...
"commits": [
{
"sha": "2bab04e050279ac078d5d34016f5dd9c466e948d",
"author": {
"email": "cloeweber@example.com",
"name": "Cloé Weber",
"date": 1671032461
},
"parents": [
"6aac318907b50252976c47e4e62ed95d438af0ea"
],
"message": "Add cron"
}
],
...
```
The `environment` property contains the settings for the environment that was pushed to:
``` json
...
"environment": {
"id": "main",
"created_at": "2022-03-22T15:47:43.750880+00:00",
"updated_at": "2022-11-29T16:16:37.085719+00:00",
"name": "main",
"machine_name": "main-abcd123",
"title": "Main",
"attributes": {},
"type": "production",
"parent": null,
"default_domain": null,
"clone_parent_on_create": true,
"deployment_target": "local",
"is_pr": false,
"status": "active",
"enable_smtp": true,
"restrict_robots": true,
"edge_hostname": "main-abcd123-abcdefgh1234567.eu-3.platformsh.site",
"deployment_state": {
"last_deployment_successful": true,
"last_deployment_at": "2022-11-29T16:16:37.085609+00:00",
"crons": {
"enabled": true,
"status": "sleeping"
}
},
"resources_overrides": {},
"last_active_at": "2022-12-13T16:07:09.788910+00:00",
"last_backup_at": null,
"project": "abcdefgh1234567",
"is_main": true,
"is_dirty": false,
"has_code": true,
"head_commit": "6aac318907b50252976c47e4e62ed95d438af0ea",
"merge_info": {
"commits_ahead": 0,
"commits_behind": 0,
"parent_ref": null
},
"has_deployment": true
},
...
```
The `deployment` property contains the settings for the deployment,
including the [image type](/create-apps/app-reference/single-runtime-image.md#types) and
[resource allocation](/manage-resources/adjust-resources).
The following example shows a shortened excerpt of the `deployment` property:
``` json
...
"deployment": {
"id": "current",
"created_at": "2022-03-22T15:48:05.396979+00:00",
"updated_at": "2022-12-14T15:41:57.264813+00:00",
"cluster_name": "abcdefgh1234567-main-abcd123",
"project_info": {
"deployment": {
"id": "current",
"created_at": "2022-03-22T15:48:05.396979+00:00",
"updated_at": "2022-12-14T15:41:57.264813+00:00",
"cluster_name": "abcdefgh1234567-main-abcd123",
"project_info": {
"name": "abcdefgh1234567",
"settings": {
"initialize": {
"values": {
"initialize": true,
"start": false,
"base": {
"files": [],
"profile": "PHP",
"config": null,
"repository": "https://github.com/platformsh-templates/php.git@master",
"title": "PHP"
}
}
},
...
"application_config_file": ".upsun/config.yaml",
"project_config_dir": ".upsun",
...
"development_service_size": "S",
"development_application_size": "S",
"enable_certificate_provisioning": true,
"certificate_style": "ecdsa",
"certificate_renewal_activity": true,
...
"cron_minimum_interval": 5,
"cron_maximum_jitter": 20,
"concurrency_limits": {
"internal": null,
"integration": 4,
"backup": 2,
"cron": 10,
"default": 2
},
...
"build_resources": {
"cpu": 1,
"memory": 2048
},
...
"max_allowed_routes": 50000,
"max_allowed_redirects_paths": 50000,
"enable_incremental_backups": true,
...
}
},
...
```
The following example shows the full activity response to a Git push:
``` json
{
"id": "a1kz6ffxui7em",
"_links": {
"self": {
"href": "https://eu-3.upsun.com/api/projects/abcdefgh1234567/activities/a1kz6ffxui7em"
},
"log": {
"href": "/api/projects/abcdefgh1234567/activities/a1kz6ffxui7em/log"
}
},
"created_at": "2022-12-14T15:41:05.821145+00:00",
"updated_at": null,
"type": "environment.push",
"parameters": {
"user": "c9926428-44dc-4b10-be03-a26dd43b44c1",
"environment": "main",
"old_commit": "6aac318907b50252976c47e4e62ed95d438af0ea",
"new_commit": "2bab04e050279ac078d5d34016f5dd9c466e948d"
},
"project": "abcdefgh1234567",
"environments": [
"main"
],
"state": "complete",
"result": "success",
"started_at": "2022-12-14T15:41:05.969872+00:00",
"completed_at": "2022-12-14T15:41:57.635442+00:00",
"completion_percent": 100,
"cancelled_at": null,
"timings": {
"wait": 0,
"parse_commits": 0.63,
"build": 0.506,
"deploy": 49.954,
"execute": 51.516
},
"log": "Found 1 new commit\n\nBuilding application 'myapp' (runtime type: php:8.0, tree: 9851a01)\n Reusing existing build for this tree ID\n\nProvisioning certificates\n Certificates\n - certificate 5093946: expiring on 2023-02-23 11:09:20+00:00, covering {,www}.main-abcd123-abcdefgh1234567.eu-3.platformsh.site\n\n\nRedeploying environment main\n Preparing deployment\n Closing service myapp\n Opening application myapp and its relationships\n Executing deploy hook for application myapp\n hello world\n\n Opening environment\n Environment configuration\n myapp (type: php:8.0, size: S, disk: 2048)\n\n Environment routes\n http://main-abcd123-abcdefgh1234567.eu-3.platformsh.site/ redirects to https://main-abcd123-abcdefgh1234567.eu-3.platformsh.site/\n http://www.main-abcd123-abcdefgh1234567.eu-3.platformsh.site/ redirects to https://www.main-abcd123-abcdefgh1234567.eu-3.platformsh.site/\n https://main-abcd123-abcdefgh1234567.eu-3.platformsh.site/ is served by application `myapp`\n https://www.main-abcd123-abcdefgh1234567.eu-3.platformsh.site/ redirects to https://main-abcd123-abcdefgh1234567.eu-3.platformsh.site/\n",
"payload": {
"user": {
"id": "c9926428-44dc-4b10-be03-a26dd43b44c1",
"created_at": "2022-12-14T15:40:16.891889+00:00",
"updated_at": null,
"display_name": "Cloé Weber"
},
"environment": {
"id": "main",
"created_at": "2022-03-22T15:47:43.750880+00:00",
"updated_at": "2022-11-29T16:16:37.085719+00:00",
"name": "main",
"machine_name": "main-abcd123",
"title": "Main",
"attributes": {},
"type": "production",
"parent": null,
"default_domain": null,
"clone_parent_on_create": true,
"deployment_target": "local",
"is_pr": false,
"status": "active",
"enable_smtp": true,
"restrict_robots": true,
"edge_hostname": "main-abcd123-abcdefgh1234567.eu-3.platformsh.site",
"deployment_state": {
"last_deployment_successful": true,
"last_deployment_at": "2022-11-29T16:16:37.085609+00:00",
"crons": {
"enabled": true,
"status": "sleeping"
}
},
"resources_overrides": {},
"last_active_at": "2022-12-13T16:07:09.788910+00:00",
"last_backup_at": null,
"project": "abcdefgh1234567",
"is_main": true,
"is_dirty": false,
"has_code": true,
"head_commit": "6aac318907b50252976c47e4e62ed95d438af0ea",
"merge_info": {
"commits_ahead": 0,
"commits_behind": 0,
"parent_ref": null
},
"has_deployment": true
},
"commits": [
{
"sha": "2bab04e050279ac078d5d34016f5dd9c466e948d",
"author": {
"email": "cloeweber@example.com",
"name": "Cloé Weber",
"date": 1671032461
},
"parents": [
"6aac318907b50252976c47e4e62ed95d438af0ea"
],
"message": "Add cron"
}
],
"commits_count": 1,
"deployment": {
"id": "current",
"created_at": "2022-03-22T15:48:05.396979+00:00",
"updated_at": "2022-12-14T15:41:57.264813+00:00",
"cluster_name": "abcdefgh1234567-main-abcd123",
"project_info": {
"name": "abcdefgh1234567",
"settings": {
"initialize": {
"values": {
"initialize": true,
"start": false,
"base": {
"files": [],
"profile": "PHP",
"config": null,
"repository": "https://github.com/platformsh-templates/php.git@master",
"title": "PHP"
}
}
},
"product_name": "Upsun",
"product_code": "upsun",
"variables_prefix": "PLATFORM_",
"bot_email": "bot@upsun.com",
"application_config_file": ".upsun/config.yaml",
"project_config_dir": ".upsun",
"use_drupal_defaults": false,
"use_legacy_subdomains": false,
"development_service_size": "S",
"development_application_size": "S",
"enable_certificate_provisioning": true,
"certificate_style": "ecdsa",
"certificate_renewal_activity": true,
"development_domain_template": null,
"enable_state_api_deployments": true,
"temporary_disk_size": null,
"cron_minimum_interval": 5,
"cron_maximum_jitter": 20,
"concurrency_limits": {
"internal": null,
"integration": 4,
"backup": 2,
"cron": 10,
"default": 2
},
"flexible_build_cache": false,
"strict_configuration": true,
"has_sleepy_crons": true,
"crons_in_git": true,
"custom_error_template": null,
"app_error_page_template": null,
"environment_name_strategy": "name-and-hash",
"data_retention": null,
"enable_codesource_integration_push": true,
"enforce_mfa": false,
"systemd": true,
"router_gen2": false,
"chorus": {
"enabled": true,
"exposed": true
},
"build_resources": {
"cpu": 1,
"memory": 2048
},
"outbound_restrictions_default_policy": "allow",
"self_upgrade": true,
"additional_hosts": {},
"max_allowed_routes": 50000,
"max_allowed_redirects_paths": 50000,
"enable_incremental_backups": true,
"sizing_api_enabled": false,
"enable_cache_grace_period": true,
"enable_zero_downtime_deployments": false,
"enable_admin_agent": true,
"certifier_url": "https://proxy.upsun.com/",
"centralized_permissions": false,
"glue_server_max_request_size": 10
}
},
"environment_info": {
"name": "main",
"is_main": true,
"is_production": false,
"reference": "refs/heads/main",
"machine_name": "main-abcd123",
"environment_type": "production"
},
"deployment_target": "local",
"vpn": null,
"http_access": {
"is_enabled": true,
"addresses": [],
"basic_auth": {}
},
"enable_smtp": true,
"restrict_robots": true,
"variables": [
{
"name": "php:memory_limit",
"value": "512M",
"is_sensitive": false
}
],
"access": [
{
"entity_id": "c9926428-44dc-4b10-be03-a26dd43b44c1",
"role": "admin"
}
],
"subscription": {
"license_uri": "https://accounts.upsun.com/api/v1/licenses/12345678",
"plan": "development",
"environments": 3,
"storage": 5120,
"included_users": 1,
"subscription_management_uri": "https://console.upsun.com//-/users/abcd12345/billing/plan/12345678",
"restricted": false,
"suspended": false,
"user_licenses": 1
},
"services": {},
"routes": {
"https://main-abcd123-abcdefgh1234567.eu-3.platformsh.site/": {
"primary": true,
"id": null,
"production_url": "https://main-abcd123-abcdefgh1234567.eu-3.platformsh.site/",
"attributes": {},
"type": "upstream",
"tls": {
"strict_transport_security": {
"enabled": null,
"include_subdomains": null,
"preload": null
},
"min_version": null,
"client_authentication": null,
"client_certificate_authorities": []
},
"original_url": "https://{default}/",
"restrict_robots": true,
"cache": {
"enabled": true,
"default_ttl": 0,
"cookies": [
"*"
],
"headers": [
"Accept",
"Accept-Language"
]
},
"ssi": {
"enabled": false
},
"upstream": "myapp:http",
"redirects": {
"expires": "-1s",
"paths": {}
}
},
"https://www.main-abcd123-abcdefgh1234567.eu-3.platformsh.site/": {
"primary": false,
"id": null,
"production_url": "https://www.main-abcd123-abcdefgh1234567.eu-3.platformsh.site/",
"attributes": {},
"type": "redirect",
"tls": {
"strict_transport_security": {
"enabled": null,
"include_subdomains": null,
"preload": null
},
"min_version": null,
"client_authentication": null,
"client_certificate_authorities": []
},
"original_url": "https://www.{default}/",
"restrict_robots": true,
"to": "https://main-abcd123-abcdefgh1234567.eu-3.platformsh.site/",
"redirects": {
"expires": "-1s",
"paths": {}
}
},
"http://main-abcd123-abcdefgh1234567.eu-3.platformsh.site/": {
"primary": false,
"id": null,
"production_url": "http://main-abcd123-abcdefgh1234567.eu-3.platformsh.site/",
"attributes": {},
"type": "redirect",
"tls": {
"strict_transport_security": {
"enabled": null,
"include_subdomains": null,
"preload": null
},
"min_version": null,
"client_authentication": null,
"client_certificate_authorities": []
},
"original_url": "http://{default}/",
"restrict_robots": true,
"to": "https://main-abcd123-abcdefgh1234567.eu-3.platformsh.site/",
"redirects": {
"expires": "-1s",
"paths": {}
}
},
"http://www.main-abcd123-abcdefgh1234567.eu-3.platformsh.site/": {
"primary": false,
"id": null,
"production_url": "http://www.main-abcd123-abcdefgh1234567.eu-3.platformsh.site/",
"attributes": {},
"type": "redirect",
"tls": {
"strict_transport_security": {
"enabled": null,
"include_subdomains": null,
"preload": null
},
"min_version": null,
"client_authentication": null,
"client_certificate_authorities": []
},
"original_url": "http://www.{default}/",
"restrict_robots": true,
"to": "https://www.main-abcd123-abcdefgh1234567.eu-3.platformsh.site/",
"redirects": {
"expires": "-1s",
"paths": {}
}
}
},
"webapps": {
"app": {
"resources": null,
"size": "AUTO",
"disk": 2048,
"access": {
"ssh": "contributor"
},
"relationships": {},
"additional_hosts": {},
"mounts": {
"/web/uploads": {
"source": "local",
"source_path": "uploads"
},
"/private": {
"source": "local",
"source_path": "private"
}
},
"timezone": null,
"variables": {},
"firewall": null,
"initial_size": null,
"container_profile": null,
"instance_count": null,
"name": "app",
"type": "php:8.0",
"runtime": {},
"preflight": {
"enabled": true,
"ignored_rules": []
},
"tree_id": "9851a01081f3c2f943f75f62c38b67f8bc0ec15c",
"slug_id": "abcdefgh1234567-app-9851a01081f3c2f943f75f62c38b67f8bc0ec15c-73985064e66fd2299f4b83931cff46891249a964",
"app_dir": "/app",
"web": {
"locations": {
"/": {
"root": "web",
"expires": "-1s",
"passthru": "/index.php",
"scripts": true,
"allow": true,
"headers": {},
"rules": {}
}
},
"move_to_root": false
},
"hooks": {
"build": "set -e\n",
"deploy": "set -e\n",
"post_deploy": null
},
"crons": {
"saybye": {
"spec": "5 * * * *",
"commands": {
"start": "sleep 60 && echo sleep-60-finished && date",
"stop": null
},
"shutdown_timeout": null,
"timeout": 86400
}
}
}
},
"workers": {},
}
}
},
"description": "Cloé Weber pushed to Main",
"text": "Cloé Weber pushed to Main",
"expires_at": "2023-12-14T15:41:05.821145+00:00"
}
```
# Manage Upsun environments [Back up an environment](https://docs.upsun.com/environments/backup.html)
When you're making changes to your apps,
you want to be sure those changes only improve things and don't make you lose any data.
You also want to have a disaster recovery plan in place.
Backups help you protect yourself against potential data loss.
You might want to create backups of your live environment before merging a different environment into it
or each time you increase the storage space of your services.
You also have regularly scheduled automated backups of your production environments to cover most cases.
Note that you can only create backups and restore active environments.
To work with an [inactive environment](/glossary.md#inactive-environment),
first activate it.
## How backup and restore works
1. As an [admin user](../administration/users.md), you can do a backup of your environment.
This backup includes the complete data and code of the environment.
All persistent data from all running [services](../add-services/_index.md)
and any files stored on [mounts](/create-apps/app-reference/single-runtime-image.md#mounts) are included.
The backup is stored internally on Upsun.
That is, the backup can be applied to environments on Upsun, but it can't be downloaded.
If you need to download backups, instead [export your mount and service data](/learn/tutorials/exporting.md)).
2. You restore your environment using the backup.
At this point, the data and code from the backup are restored to ensure a consistent state.
The latest code in your repository may have been modified such that it no longer works correctly with the old, restored data.
Warning
Upsun does not modify your Git repository. Any further changes you make use the latest code in your repository.
3. Depending on your needs, you can do the following:
a) To use the code from the time of the backup as a baseline for future changes,
make sure you restore it yourself in your Git repository.
To do so, use Git commands such as `revert`.
b) To use your latest code instead, just redeploy your environment or push a new change.
Note
You may not want the code from the backup to be restored at step 2.
For instance, if you have deleted containers since the backup, you may not want them to be restored with the backup.
In this case, you can opt out of restoring the code.
To do so, when you restore your backup, use the --no-code flag.
## Backups and downtime
By default, creating a manual backup causes a momentary pause in site availability so that all requests can complete.
This means the environment is backed up in a known consistent state.
The total interruption is usually only 15 to 30 seconds.
Any requests during that time are held temporarily, not dropped.
To avoid this downtime, use [live backups](#live-backups).
For consistent backups, create the backups during non-peak hours for your site.
## Data retention
### Manual backups
[Manual backups](../environments/backup.md#create-a-manual-backup) are retained until you delete them or replace them with another backup.
You can configure the maximum number of manual backups. Once that number is reached, any new manual backup automatically replaces the oldest backup.
### Automated backups
Automated backups are retained for 2 days when you use the [default backup policy](#default-backup-policy)
(meaning, 2 days worth of backups are retained at any given point).
When you [configure your own automated backup policy](#configure-a-backup-policy),
the retention time varies based on that configuration.
Automated backups are always [live](#live-backups).
## Backup policy
### Default backup policy
By default, Upsun provides 1 automated backup a day for your production environment,
with a [2-day retention](/security/data-retention.md) (2 days worth of backups are retained at any given point).
You can [configure your own backup policy](#configure-a-backup-policy).
The default backup policy is equivalent to a custom backup policy using a `1d` interval and a count of `2` (see below).
### Configure a backup policy
Upsun allows you to fully configure your own backup policy.
You can setup a different automated backup schedule per environment type (production, staging, and development environments).
On a given environment type, you can configure:
- The total number of backups (manual and automated)
- The total number of manual backups specifically
- Multiple schedules for automated backups
An automated backup schedule is composed of an interval and a count.
The interval defines the frequency of the backups.
An interval can be a couple of hours, days, weeks, months, or years.
To configure an interval, use the following values:
- ``h`` for hour
- ``d`` for day
- ``w`` for week
- ``M`` for month
- ``y`` for year
The count defines the number of backups to retain.
### Configuration examples
To take a backup every day and keep up to 7 backups,
run the following command:
```bash {location="Terminal"}
upsun project:curl settings -X PATCH \
-d '{
"data_retention": {
"production": {
"default_config": {
"schedule": [
{"interval": "1d", "count": 7},
]
}
}
}
}'
```
#### Configure multiple automated backup schedules
You can use multiple schedules to implement you own backup policy.
For instance, you may want to keep multiple recent backups and fewer older backups,
using a command similar to the following:
```bash {location="Terminal"}
upsun project:curl settings -X PATCH \
-d '{
"data_retention": {
"production": {
"default_config": {
"schedule": [
{"interval": "1d", "count": 7},
{"interval": "1w", "count": 4},
{"interval": "1M", "count": 12}
]
}
}
}
}'
```
The command results in:
- A backup every day for 7 days
- A backup every week for 4 weeks
- A backup every month for 12 months
#### Set a limit for backups
To configure the maximum number of backups (automated and manual backups alike) on your production environment,
run a command similar to the following:
```bash {location="Terminal"}
upsun project:curl /settings -X PATCH -d '{"data_retention": {"production": {"max_backups": 10}}}'
```
To configure the maximum number of manual backups on the production environment,
run a command similar to the following:
```bash {location="Terminal"}
upsun project:curl /settings -X PATCH -d '{"data_retention": {"production": {"default_config": {"manual_count": 1}}}}'
```
## Live backups
You can create backups without any downtime.
This means your environment is running and open to connections during the backup.
Because the connections may come in during backup creation, live backups may have data inconsistencies among containers.
They may make restorations less reliable.
To avoid such issues, schedule [manual backups](#create-a-manual-backup) during non-peak hours,
when the short amount of downtime is least noticed.
You can create a manual live backup on a Grid project:
## Create a manual backup
You can create a manual backup using the [CLI](../administration/cli/_index.md) or in the [Console](../administration/web/_index.md).
See more information on [backup policies](#backup-policy) and [data retention](#data-retention).
### Automate manual backups
You can also automate the process of creating manual backups through [cron jobs](/create-apps/app-reference/single-runtime-image.md#crons).
The cron job uses the CLI command to back up the environment.
It requires you to [set up the CLI on the environment with an API token](../administration/cli/api-tokens.md#authenticate-in-an-environment).
Although this process is automated,
backups created in this way count as [manual backups](#manual-backups).
They don't affect the automated backups taken as part of [a schedule](#configure-a-backup-policy).
## Physical storage location
Backups are stored as binary large objects separate from your environments.
This storage is replicated over multiple data centers in different locations
[within the region your project is hosted in](https://platform.sh/trust-center/security/data-security/).
This means that in the rare event a data center becomes unavailable, your backups are still available.
# Integrations [External Integrations](https://docs.upsun.com/integrations/overview.html)
Upsun can be integrated with external services.
Upsun supports native integrations with multiple services, first and foremost Git hosting services such as GitHub, GitLab, or Bitbucket.
You can continue to use those tools for your development workflow, and have Upsun environments created automatically for your pull requests and branches.
## List active integrations
With the CLI, you can list all your active integrations using the following command:
```bash
upsun integrations
```
You get output similar to the following:
```bash
+---------------+-------------+-------------------------------------------------------------------------------------+
| ID | Type | Summary |
+---------------+-------------+-------------------------------------------------------------------------------------+
| abcdefghijklm | github | Repository: platformsh/platformsh-docs |
| | | Hook URL: |
| | | https://eu-3.platform.sh/api/projects/123abcdefgh3i/integrations/abcdefghijklm/hook |
+---------------+-------------+-------------------------------------------------------------------------------------+
```
## Validate integrations
Once your integration has been configured, you can check that it's working as expected.
To do so, follow these steps:
1. Run the `upsun integration:validate` command.
2. When prompted, select the integration you want to validate:
```bash
Enter a number to choose an integration:
[0] 5aut2djgt6kdd (health.slack)
[1] a6535j9qp4sl8 (github)
> 1
```
You get output similar to:
```bash
Validating the integration a6535j9qp4sl8 (type: github)...
The integration is valid.
```
## Debug integrations
When integrations run, they trigger "activities." Activities are actions that happen on Upsun, and they get logged.
Usually these are triggered nearly instantaneously on the webhook endpoint.
These activities may be delayed due to the external services having latency.
Those logs are available via the CLI.
In most cases they aren't necessary but may be useful for debugging an integration if it is misbehaving for some reason.
There are a handful of CLI commands available, all under the `integrations` section.
### List all activities
To list all the updates triggered by [activities](../integrations/activity/reference.md) on a given project and integration,
follow these steps:
1. Run the `upsun integration:activities` command.
2. When prompted, select an integration.
```bash
Enter a number to choose an integration:
[0] dxr45hfldrkoe (webhook)
[1] n2ukd4p7qofg4 (health.email)
[2] c4opi5tjv3yfd (github)
> 2
```
You get output similar to the following:
```bash
Activities on the project Upsun | Docs (6b2eocegfkwwg), integration c4opi5tjv3yfd (github):
+---------------+---------------------------+-------------------------------------------------------------+----------+---------+
| ID | Created | Description | State | Result |
+---------------+---------------------------+-------------------------------------------------------------+----------+---------+
| 6456zmdtoykxa | 2020-04-14T16:38:09-05:00 | Fetching from https://github.com/platformsh/platformsh-docs | complete | success |
| wcwp34yjvydgk | 2020-04-14T16:35:22-05:00 | Fetching from https://github.com/platformsh/platformsh-docs | complete | success |
| w2bp3oa5xbfoe | 2020-04-14T16:33:13-05:00 | Fetching from https://github.com/platformsh/platformsh-docs | complete | success |
| uqqvdyxmcdmsa | 2020-04-14T16:31:45-05:00 | Fetching from https://github.com/platformsh/platformsh-docs | complete | success |
| 7x3wefhh4fwqc | 2020-04-14T16:30:36-05:00 | Fetching from https://github.com/platformsh/platformsh-docs | complete | success |
| a46aah3ga65gc | 2020-04-14T16:29:46-05:00 | Fetching from https://github.com/platformsh/platformsh-docs | complete | success |
| r7erid2jlixgi | 2020-04-14T16:24:50-05:00 | Fetching from https://github.com/platformsh/platformsh-docs | complete | success |
| ieufk3vvde5oc | 2020-04-14T16:24:49-05:00 | Fetching from https://github.com/platformsh/platformsh-docs | complete | success |
| bc7ghg36ty4ea | 2020-04-14T15:30:17-05:00 | Fetching from https://github.com/platformsh/platformsh-docs | complete | success |
| 4qojtv7a6rk2w | 2020-04-14T15:27:26-05:00 | Fetching from https://github.com/platformsh/platformsh-docs | complete | success |
+---------------+---------------------------+-------------------------------------------------------------+----------+---------+
```
You may also specify an integration to display in the command line directly: `upsun integration:activities c4opi5tjv3yfd`.
The ID is an internal identifier for the activity event.
The Description field is an arbitrary string of text produced by the integration code.
The State and Result fields indicate if the activity completed successfully, failed for some reason, or is currently in progress.
See the `--help` output of the command for more options.
### Show detailed information on an activity
To show detailed information on a specific activity,
run the following command:
```bash
upsun integration:activity:log INTEGRATION_IDACTIVITY_ID -t
```
The `-t` option specifies that timestamps must be included in the display of the results.
You get output similar to the following:
```bash
Integration ID: ceopz5tgj3yfc
Activity ID: 6456zmdtoykxa
Type: integration.github.fetch
Description: Fetching from https://github.com/platformsh/platformsh-docs
Created: 2020-04-15T08:44:07-05:00
State: complete
Log:
[2020-04-15T13:44:17-05:00] Waiting for other activities to complete
[2020-04-15T13:46:07-05:00] Fetching from GitHub repository platformsh/platformsh-docs
[2020-04-15T13:46:09-05:00] No changes since last fetch
[2020-04-15T13:46:09-05:00]
[2020-04-15T13:46:09-05:00] Synchronizing branches
[2020-04-15T13:46:09-05:00]
[2020-04-15T13:46:09-05:00] Synchronizing pull requests
[2020-04-15T13:46:59-05:00]
[2020-04-15T13:46:59-05:00] W: No changes found, scheduling a retry..
```
That shows the full output of the activity, including timestamps.
That can be especially helpful if trying to determine why an integration isn't behaving as expected.
See the `--help` output of the command for more options.
If you omit the activity ID (the second random-seeming string), the command will default to the most recent activity recorded.
# Add services [PostgreSQL (Database service)](https://docs.upsun.com/add-services/postgresql.html)
PostgreSQL is a high-performance, standards-compliant relational SQL database.
See the [PostgreSQL documentation](https://www.postgresql.org/docs/9.6/index.html) for more information.
## Supported versions
You can select the major version. But the latest compatible minor version is applied automatically and can’t be overridden.
Patch versions are applied periodically for bug fixes and the like. When you deploy your app, you always get the latest available patches.
### Deprecated versions
The following versions are [deprecated](/glossary.html#deprecated-versions).
They're available, but they aren't receiving security updates from upstream and aren't guaranteed to work.
They'll be removed in the future,
so migrate to one of the [supported versions](#supported-versions).
11
10
9.6
9.5
9.4
9.3
## Relationship reference
For each service [defined via a relationship](#usage-example) to your application,
Upsun automatically generates corresponding environment variables within your application container,
in the ``$_`` format.
Here is example information available through the [service environment variables](/development/variables/_index.md#service-environment-variables) themselves,
or through the [``PLATFORM_RELATIONSHIPS`` environment variable](/development/variables/use-variables.md#use-provided-variables).
You can obtain the complete list of available service environment variables in your app container by running upsun ssh env.
Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the service environment variables directly rather than hard coding any values.
For some advanced use cases, you can use the PLATFORM_RELATIONSHIPS environment variable.
The structure of the PLATFORM_RELATIONSHIPS environment variable can be obtained by running upsun relationships in your terminal:
# Decode the built-in credentials object variable.exportRELATIONSHIPS_JSON=$(echo$PLATFORM_RELATIONSHIPS| base64 --decode)# Set environment variables for individual credentials.exportAPP_POSTGRESQL_HOST="$(echo$RELATIONSHIPS_JSON| jq -r '.postgresql[0].host')"
## Usage example
### 1. Configure the service
To define the service, use the ``postgresql`` type:
```yaml {configFile="app"}
services:
# The name of the service container. Must be unique within a project.
:
type: postgresql:
```
Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service.
### 2. Define the relationship
To define the relationship, use the following configuration:
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<SERVICE_NAME>:
You can define <SERVICE_NAME> as you like, so long as it’s unique between all defined services
and matches in both the application and services configuration.
The example above leverages default endpoint configuration for relationships.
That is, it uses default endpoints behind-the-scenes, providing a relationship
(the network address a service is accessible from) that is identical to the name of that service.
With the above definition, the application container (<APP_NAME>) now has access to the service via the relationship <SERVICE_NAME> and its corresponding service environment variables.
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<RELATIONSHIP_NAME>:service:<SERVICE_NAME>endpoint:postgresql
You can define <SERVICE_NAME> and <RELATIONSHIP_NAME> as you like, so long as it’s unique between all defined services and relationships
and matches in both the application and services configuration.
The example above leverages explicit endpoint configuration for relationships.
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# PHP extensions.runtime:extensions:- pdo_pgsql# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<SERVICE_NAME>:
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# PHP extensions.runtime:extensions:- pdo_pgsql# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<RELATIONSHIP_NAME>:service:<SERVICE_NAME>endpoint:postgresql
applications:# The name of the app container. Must be unique within a project.myapp:# PHP extensions.runtime:extensions:- pdo_pgsql# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:postgresql:services:# The name of the service container. Must be unique within a project.postgresql:type:postgresql:16
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# PHP extensions.runtime:extensions:- pdo_pgsql# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:postgresql:service:postgresqlendpoint:postgresqlservices:# The name of the service container. Must be unique within a project.postgresql:type:postgresql:16
### Use in app
To use the configured service in your app, add a configuration file similar to the following to your project.
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"# PHP extensions.runtime:extensions:- pdo_pgsql[...]# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:postgresql:services:# The name of the service container. Must be unique within a project.postgresql:type:postgresql:16
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"# PHP extensions.runtime:extensions:- pdo_pgsql[...]# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:postgresql:service:postgresqlendpoint:postgresqlservices:# The name of the service container. Must be unique within a project.postgresql:type:postgresql:16
This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory.
`myapp` has access to the `postgresql` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship)
(as per [default endpoint](/create-apps/app-reference/single-runtime-image#relationships) configuration for relationships).
From this, ``myapp`` can retrieve access credentials to the service through the [relationship environment variables](#relationship-reference).
```bash {location="myapp/.environment"}
# Set environment variables for individual credentials.
# For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables.
export DB_CONNECTION="${POSTGRESQL_SCHEME}"
export DB_USERNAME="${POSTGRESQL_USERNAME}"
export DB_PASSWORD="${POSTGRESQL_PASSWORD}"
export DB_HOST="${POSTGRESQL_HOST}"
export DB_PORT="${POSTGRESQL_PORT}"
export DB_DATABASE="${POSTGRESQL_PATH}"
# Surface connection string variable for use in app.
export DATABASE_URL="${DB_CONNECTION}://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_DATABASE}"
```
The above file — ``.environment`` in the ``myapp`` directory — is automatically sourced by Upsun into the runtime environment, so that the variable ``DATABASE_URL`` can be used within the application to connect to the service.
Note that ``DATABASE_URL``, and all Upsun [service environment variables](/development/variables/_index.md#service-environment-variables) like ``POSTGRESQL_HOST``, are environment-dependent.
Unlike the build produced for a given commit,
they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment.
A file very similar to this is generated automatically for your when using the ``upsun ify`` command to [migrate a codebase to Upsun](/get-started/_index.md).
## Access the service directly
Access the service using the Upsun CLI by running `upsun sql`.
You can also access it from your app container via [SSH](../development/ssh/_index.md).
From your [relationship data](#relationship-reference), you need: `POSTGRESQL_USERNAME`, `POSTGRESQL_HOST`, and `POSTGRESQL_PORT`.
Then run the following command:
```bash
psql -U POSTGRESQL_USERNAME -h POSTGRESQL_HOST -p POSTGRESQL_PORT
```
Using the values from the [example](#relationship-reference), that would be:
```bash
psql -U main -h postgresql.internal -p 5432
```
You can obtain the complete list of available service environment variables in your app container by running ``upsun ssh env``.
Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the [service environment variables](/development/variables/_index.md#service-environment-variables) directly rather than hard coding any values.
## Exporting data
The easiest way to download all data in a PostgreSQL instance is with the Upsun CLI. If you have a single SQL database, the following command exports all data using the `pg_dump` command to a local file:
```bash
upsun db:dump
```
If you have multiple SQL databases it prompts you which one to export. You can also specify one by relationship name explicitly:
```bash
upsun db:dump --relationship postgresql
```
By default the file is uncompressed. If you want to compress it, use the `--gzip` (`-z`) option:
```bash
upsun db:dump --gzip
```
You can use the `--stdout` option to pipe the result to another command. For example, if you want to create a bzip2-compressed file, you can run:
```bash
upsun db:dump --stdout | bzip2 > dump.sql.bz2
```
It is also possible to generate the dump locally if you have the `pg_dump` command installed with `upsun tunnel:single`. The command will first ask for the service and then will provide a prompt for the URI string that you can use. For example:
```bash
pg_dump -d postgresql://REPLACE_URI_FROM_OUTPUT -f dump.sql
```
## Importing data
Make sure that the imported file contains objects with cleared ownership and `IF EXISTS` clauses. For example, you can create a DB dump with following parameters:
```bash
pg_dump --no-owner --clean --if-exists
```
The easiest way to load data into a database is to pipe an SQL dump through the `upsun sql` command, like so:
```bash
upsun sql < my_database_backup.sql
```
That runs the database backup against the SQL database on Upsun.
That works for any SQL file, so the usual caveats about importing an SQL dump apply
(for example, it's best to run against an empty database).
As with exporting, you can also specify a specific environment to use and a specific database relationship to use, if there are multiple.
```bash
upsun sql --relationship postgresql -e BRANCH_NAME < my_database_backup.sql
```
Note
Importing a database backup is a destructive operation. It overwrites data already in your database.
Taking a backup or a database export before doing so is strongly recommended.
## Sanitizing data
To ensure people who review code changes can't access personally identifiable information stored in your database,
[sanitize your preview environments](../development/sanitize-db/postgresql.md).
## Multiple databases
If you are using version `10`, `11`, `12`, `13`, or later of this service,
it's possible to define multiple databases as well as multiple users with different permissions.
To do so requires defining multiple endpoints.
Under the `configuration` key of your service there are two additional keys:
* `databases`: This is a YAML array listing the databases that should be created. If not specified, a single database named `main` is created.
Note that removing a schema from the list of `schemas` on further deployments results in **the deletion of the schema.**
* `endpoints`: This is a nested YAML object defining different credentials. Each endpoint may have access to one or more schemas (databases), and may have different levels of permission for each. The valid permission levels are:
* `ro`: Using this endpoint only `SELECT` queries are allowed.
* `rw`: Using this endpoint `SELECT` queries as well as `INSERT`/`UPDATE`/`DELETE` queries are allowed.
* `admin`: Using this endpoint all queries are allowed, including DDL queries (`CREATE TABLE`, `DROP TABLE`, etc.).
Consider the following illustrative example:
```yaml {configFile="services"}
services:
# The name of the service container. Must be unique within a project.
postgresql:
type: "postgresql:16"
configuration:
databases:
- main
- legacy
endpoints:
admin:
privileges:
main: admin
legacy: admin
reporter:
default_database: main
privileges:
main: ro
importer:
default_database: legacy
privileges:
legacy: rw
```
This example creates a single PostgreSQL service named `postgresql`. The server has two databases, `main` and `legacy` with three endpoints created.
* `admin`: has full access to both databases.
* `reporter`: has `SELECT` query access to the `main` database, but no access to `legacy`.
* `importer`: has `SELECT`/`INSERT`/`UPDATE`/`DELETE` access (but not DDL access) to the `legacy` database. It doesn't have access to `main`.
If a given endpoint has access to multiple databases you should also specify which is listed by default in the relationships array. If one isn't specified, the `path` property of the relationship is `null`. While that may be acceptable for an application that knows the name of the database it's connecting to, automated tools like the Upsun CLI can't access the database on that relationship. For that reason, defining the `default_database` property is always recommended.
Once these endpoints are defined, you need to expose them to your application as a relationship. Continuing with the above example, your `relationships` in `.upsun/config.yaml` might look like:
```yaml {configFile="app"}
applications:
# The name of the app container. Must be unique within a project.
myapp:
source:
root: "/"
[...]
# Relationships enable access from this app to a given service.
# The example below shows configuration with explicitly set service names and endpoints.
# See the Application reference for all options for defining relationships and endpoints.
relationships:
database:
service: postgresql
endpoint: admin
reports:
service: postgresql
endpoint: reporter
imports:
service: postgresql
endpoint: importer
services:
# The name of the service container. Must be unique within a project.
postgresql:
type: "postgresql:16"
configuration:
databases:
- main
- legacy
endpoints:
admin:
privileges:
main: admin
legacy: admin
reporter:
default_database: main
privileges:
main: ro
importer:
default_database: legacy
privileges:
legacy: rw
```
Each database is accessible to your application through the `database`, `reports`, and `imports` relationships.
They'll be available in the [service environment variables](/development/variables/_index.md#service-environment-variables) and all have the same structure documented [above](#relationship-reference), but with different credentials. You can use those to connect to the appropriate database with the specified restrictions using whatever the SQL access tools are for your language and application.
A service configuration without the `configuration` block defined is equivalent to the following default values:
```yaml {configFile="services"}
services:
# The name of the service container. Must be unique within a project.
postgresql:
type: "postgresql:16"
configuration:
databases:
- main
endpoints:
postgresql:
default_database: main
privileges:
main: admin
```
If you do not define `database` but `endpoints` are defined, then the single database `main` is created with the following assumed configuration:
```yaml {configFile="services"}
services:
# The name of the service container. Must be unique within a project.
postgresql:
type: "postgresql:16"
configuration:
databases:
- main
endpoints:
```
Alternatively, if you define multiple databases but no endpoints, a single user `main` is created with `admin` access to each of your databases, equivalent to the configuration below:
```yaml {configFile="services"}
services:
# The name of the service container. Must be unique within a project.
postgresql:
type: "postgresql:16"
configuration:
databases:
- firstdb
- seconddb
- thirddb
endpoints:
main:
firstdb: admin
seconddb: admin
thirddb: admin
```
## Password generation
When you connect your app to a database,
an empty password is generated for the database by default.
This can cause issues with your app.
To generate real passwords for your database,
define custom endpoints in your [service configuration](#1-configure-the-service).
For each custom endpoint you create,
you get an automatically generated password,
similarly to when you create [multiple databases](#multiple-databases).
Note that you can't customize these automatically generated passwords.
After your custom endpoints are exposed as relationships in your [app configuration](../../create-apps/_index.md),
you can retrieve the password for each endpoint
through the [service environment variables](/development/variables/_index.md#service-environment-variables) within your [application containers](/development/variables/use-variables.md#access-variables-in-your-app).
The password value changes automatically over time, to avoid downtime its value has to be read dynamically by your app.
Globally speaking, having passwords hard-coded into your codebase can cause security issues and should be avoided.
When you switch from the default configuration with an empty password to custom endpoints,
make sure your service name remains unchanged.
Failure to do so results in the creation of a new service,
which removes any existing data from your database.
## Service timezone
To change the timezone for the current session, run `SET TIME ZONE TIMEZONE;`.
## Extensions
Upsun supports a number of PostgreSQL extensions. To enable them, list them under the `configuration.extensions` key in your `.upsun/config.yaml` file, like so:
```yaml {configFile="services"}
services:
# The name of the service container. Must be unique within a project.
postgresql:
type: "postgresql:16"
configuration:
extensions:
- pg_trgm
- hstore
```
In this case, you have `pg_trgm` installed, providing functions to determine the similarity of text based on trigram matching, and `hstore` providing a key-value store.
### Available extensions
The following is the extensive list of supported extensions. Note that you can't currently add custom
extensions not listed here.
* `address_standardizer` - Used to parse an address into constituent elements. Generally used to support geocoding address normalization step.
* `address_standardizer_data_us` - For standardizing addresses based on US dataset example
* `adminpack` - administrative functions for PostgreSQL
* `autoinc` - functions for auto-incrementing fields
* `bloom` - bloom access method - signature file based index (requires 9.6 or higher)
* `btree_gin` - support for indexing common data types in GIN
* `btree_gist` - support for indexing common data types in GiST
* `chkpass` - data type for auto-encrypted passwords
* `citext` - data type for case-insensitive character strings
* `cube` - data type for multidimensional cubes
* `dblink` - connect to other PostgreSQL databases from within a database
* `dict_int` - text search dictionary template for integers
* `dict_xsyn` - text search dictionary template for extended synonym processing
* `earthdistance` - calculate great-circle distances on the surface of the Earth
* `file_fdw` - foreign-data wrapper for flat file access
* `fuzzystrmatch` - determine similarities and distance between strings
* `hstore` - data type for storing sets of (key, value) pairs
* `insert_username` - functions for tracking who changed a table
* `intagg` - integer aggregator and enumerator (obsolete)
* `intarray` - functions, operators, and index support for 1-D arrays of integers
* `isn` - data types for international product numbering standards
* `lo` - Large Object maintenance
* `ltree` - data type for hierarchical tree-like structures
* `moddatetime` - functions for tracking last modification time
* `pageinspect` - inspect the contents of database pages at a low level
* `pg_buffercache` - examine the shared buffer cache
* `pg_freespacemap` - examine the free space map (FSM)
* `pg_prewarm` - prewarm relation data (requires 9.6 or higher)
* `pg_stat_statements` - track execution statistics of all SQL statements executed
* `pg_trgm` - text similarity measurement and index searching based on trigrams
* `pg_visibility` - examine the visibility map (VM) and page-level visibility info (requires 9.6 or higher)
* `pgcrypto` - cryptographic functions
* `pgrouting` - pgRouting Extension (requires 9.6 or higher)
* `pgrowlocks` - show row-level locking information
* `pgstattuple` - show tuple-level statistics
* `plpgsql` - PL/pgSQL procedural language
* `postgis` - PostGIS geometry, geography, and raster spatial types and functions
* `postgis_sfcgal` - PostGIS SFCGAL functions
* `postgis_tiger_geocoder` - PostGIS tiger geocoder and reverse geocoder
* `postgis_topology` - PostGIS topology spatial types and functions
* `postgres_fdw` - foreign-data wrapper for remote PostgreSQL servers
* `refint` - functions for implementing referential integrity (obsolete)
* `seg` - data type for representing line segments or floating-point intervals
* `sslinfo` - information about SSL certificates
* `tablefunc` - functions that manipulate whole tables, including `crosstab`
* `tcn` - Triggered change notifications
* `timetravel` - functions for implementing time travel
* `tsearch2` - compatibility package for pre-8.3 text search functions (obsolete, only available for 9.6 and 9.3)
* `tsm_system_rows` - TABLESAMPLE method which accepts number of rows as a limit (requires 9.6 or higher)
* `tsm_system_time` - TABLESAMPLE method which accepts time in milliseconds as a limit (requires 9.6 or higher)
* `unaccent` - text search dictionary that removes accents
* `uuid-ossp` - generate universally unique identifiers (UUIDs)
* `vector` - Open-source [vector](https://github.com/pgvector/pgvector) similarity search for PostgreSQL 11+
* `xml2` - XPath querying and XSLT
## Notes
### Could not find driver
If you see this error: `Fatal error: Uncaught exception 'PDOException' with message 'could not find driver'`, this means you are missing the `pdo_pgsql` PHP extension. You need to enable it in your `.upsun/config.yaml` ([see above](#1-configure-the-service)).
## Upgrading
PostgreSQL 10 and later include an upgrade utility that can convert databases from previous versions to version 10 or later. If you upgrade your service from a previous version of PostgreSQL to version 10 or above, it upgrades automatically.
The utility can't upgrade PostgreSQL 9 versions, so upgrades from PostgreSQL 9.3 to 9.6 aren't supported. Upgrade straight to version 11 instead.
Note
Make sure you first test your migration on a separate branch.
Also, be sure to take a backup of your production environment before you merge this change.
Warning
Downgrading isn’t supported. If you need to downgrade, dump to SQL, remove the service, recreate the service, and import your dump.
### Upgrade to PostgreSQL 12 with the `postgis` extension
You can't upgrade to PostgreSQL 12 with the `postgis` extension enabled.
It involves a change to a major version that results in a failed deployment that requires support intervention to fix.
Upgrading from 12 to a higher version is possible.
If you need to upgrade to version 12, follow the same steps recommended for downgrading:
1. Dump the database.
2. Remove the service.
3. Create a new service with PostgreSQL 12.
4. Import the dump to that service.
# Manage Upsun environments [Restore an environment from a backup](https://docs.upsun.com/environments/restore.html)
Once you have [backups of your environment](./backup.md), you can restore data from a previous point.
To restore an environment, you need an [Admin role for that environment type](../administration/users.md).
## 1. List available backups
To restore an environment, first select one of the available backups:
Press enter to agree with the consequences and continue.
Next to the backup you’ve selected, click More .
Click Restore.
Read through the consequences and click Yes, Restore.
The data is restored and your backed-up environment is deployed.
This deployment uses the built app, including variables, from when the backup was taken.
Warning
The code is also initially restored, but Upsun doesn’t modify your Git repository.
So any future (re)deployments use the current Git repository to build the environment.
To restore your code to its previous state when the backup was taken,
use Git commands such as revert.
Note that you can also opt out of restoring the code entirely by using the --no-code flag.
For more information, see how backup and restore works on Upsun.
## Restore to a different environment
You can restore backups to a different environment than they were created on using the CLI:
1. Switch to the branch where the backup was created.
2. To restore your backup to an existing environment, run the following command:
```bash
upsun backup:restore --target=TARGET_ENVIRONMENT_NAMEBACKUP_ID
```
If your target environment doesn't exist yet, you can create it by [branching an existing environment](/glossary.md#branch).
The new target environment will be an exact copy of the existing (parent) environment.
To do so, use the `--branch-from` option to specify the parent of your new target environment:
```bash
upsun backup:restore --target=TARGET_ENVIRONMENT_NAME --branch-from=PARENT_ENVIRONMENT_NAMEBACKUP_ID
```# YAML [What YAML is](https://docs.upsun.com/learn/overview/yaml/what-is-yaml.html)
[YAML](https://en.wikipedia.org/wiki/YAML) is a human-readable format for data serialization.
This means it can be used for structured data, like what you can find in configuration files.
Some basic rules about YAML files:
- YAML files end in `.yaml`.
Some other systems use the alternative `.yml` extension.
- YAML is case-sensitive.
- YAML is whitespace-sensitive and indentation defines the structure,
but it doesn't accept tabs for indentation.
- Empty lines are ignored.
- Comments are preceded by an octothorpe `#`.
## Data types
YAML represents data through three primitive data structures:
- Scalars (strings/numbers/booleans)
- Mappings (dictionaries/objects)
- Sequences (arrays/lists)
### Scalars (strings/numbers/booleans)
The most straightforward data structure involves defining key–value pairs where the values are strings or integers.
So you could have a basic configuration for an app:
```yaml {configFile="app"}
applications:
myapp:
type: "golang:1.18"
source:
root: /app
hooks:
build: ./build.sh
```
You can spot three key–value pairs:
| Key | Value |
| ------------------- |-------------------- |
| `type` | "golang:1.18" |
| `root` | root: /app |
| `build ` | ./build.sh |
You can define strings either with or without quotes, which can be single `'` or double `"`.
Quotes let you escape characters (if double) and make sure the value is parsed as a string when you want it.
For example, you might be representing version numbers and want to parse them as strings.
If you use `version: 1.10`, it's parsed as an integer and so is treated the same as `1.1`.
If you use `version: "1.10"`, it's parsed as a string and isn't treated as the same as `1.1`.
### Mappings (dictionaries/objects)
In addition to basic scalar values, each key can also represent a set of other key–value pairs.
So you can define entire dictionaries of pairs.
The structure of the mapping is determined by the indentation.
So children are indented more than parents and siblings have the same amount of indentation.
The exact number of spaces in the indentation isn't important, just the level relative to the rest of the map.
In contrast, when you define mappings, the order doesn't matter.
So you could expand the configuration from before to add another mapping:
```yaml {configFile="app"}
applications:
myapp:
type: "golang:1.18"
web:
commands:
start: ./bin/app
locations:
'/':
passthru: true
allow: false
```
This creates a `web` dictionary that has two dictionaries within it: `commands` and `locations`,
each with their own mappings:
- `web` → `commands` → `start: ./bin/app`
- `web` → `locations` → `'/'` → `passthru: true` and `allow: false`
### Sequences (arrays/lists)
In addition to maps defining further key–value pairs, you can also use sequences to include lists of information.
```yaml {configFile="app"}
applications:
myapp:
web:
locations:
'/':
index:
- index.html
- index.htm
passthru: true
allow: false
```
You can also define sequences using a flow syntax:
```yaml {configFile="app"}
applications:
myapp:
web:
locations:
'/':
index: [index.html, index.htm]
passthru: true
allow: false
```
In either case, you get a list of values within `index`:
`web` → `locations` → `'/'` → `index` → `index.html` and `index.htm`
## Define multi-line strings
If you have a long string that spans multiple lines, use a pipe `|` to preserve line breaks.
The new lines need to have at least the same indentation as the first
(you can add more indentation that's then preserved).
So you could add a multi-line string to a `build` key in the `hooks` map:
```yaml {configFile="app"}
applications:
myapp:
hooks:
build: |
set -x -e
cp a.txt b.txt
```
And the resulting value preserves the line break.
This lets you do things like enter small shell scripts within a YAML file.
`hooks` → `build` → `set -x -e` and `cp a.txt b.txt`
## Reuse content
YAML supports internal named references, known as anchors, which can be referenced using an alias.
This allows you to reuse YAML blocks in multiple places within a single file.
Define an anchor by adding `&` to the start of a value, where `` is a unique identifier.
The anchor represents this entire value.
Then refer to the anchor using `*`.
The following example shows 4 different workers:
```yaml {configFile="app"}
applications:
myapp:
# ...
workers:
queue1: &runner
commands:
start: python queue-worker.py
queue2: *runner
queue3:
<<: *runner
```
All of the workers above are identical to each other.
Note that you need to place an alias with `<<:` at the same level as the other keys within that value.
## What's next
- See what Upsun makes possible with [custom tags](./platform-yaml-tags.md).
- Read everything that's possible with YAML in the [YAML specification](https://yaml.org/spec/1.2.2/).
- See a [YAML file that explains YAML syntax](https://learnxinyminutes.com/docs/yaml/).
# YAML [{{% vendor/name %}} YAML structure](https://docs.upsun.com/learn/overview/yaml/yaml-structure.html)
In addition to the [basic functions you should be familiar with](./what-is-yaml.md), YAML structure is important.
Upsun accepts a specific structure for YAML configuration files.
## YAML file location
When you run the [`upsun project:init` command](/get-started/here/configure/_index.md), a default ``config.yaml`` file is generated in the `.upsun` folder. It contains the minimum default configuration based on your detected local stack.
This YAML file is located in your ``.upsun`` directory, at the root of your project source code, and is a good starting point before customization.
```bash
.
├── .upsun
| └── config.yaml
└──
```
## Mandatory top-level keys
In the ``config.yaml`` file, there are only three mandatory top-level YAML keys:
- ``applications``: this section of the file contains all of your [app definitions](/create-apps/app-reference/single-runtime-image)
- ``routes``: this section of the file contains all of your [route definitions](/define-routes) (for each of your apps)
- ``services``: this section of the file contains all of your [service definitions](/add-services) (for each of your apps)
This looks like:
```yaml {location="apps"}
applications:
myapp:
...
services:
mariadb:
type: mariadb:10.6 # All available versions are: 10.6, 10.5, 10.4, 10.3
routes:
"https://{default}/":
type: upstream
upstream: "myapp:http"
```
Below these three top-level key sections, you can use any of the [available YAML tags](./platform-yaml-tags.md) you need.
Note
Any YAML files located at the first level of your .upsun folder, at the root of your project source code, are taken in account. See Rules on YAML files.
## Rules on YAML files
The following rules apply to YAML files contained in the ``.upsun`` folder:
- All the existing YAML files located at the first level of the ``.upsun`` folder are taken into account.
- All the existing YAML files located at the first level of the ``.upsun`` folder must feature the [mandatory top-level keys](#mandatory-top-level-keys), and must contain a [valid YAML configuration](/create-apps/app-reference/single-runtime-image.md).
- All the YAML files in subdirectories of the ``.upsun`` folder need to be [manually imported](/learn/overview/yaml/platform-yaml-tags.md#include) and contain a [valid YAML configuration](/create-apps/app-reference/single-runtime-image.md).
Warning
When Upsun combines all the YAML files located at the first level of the .upsun folder, only the top-level keys (applications, services, and routes) are merged. So if you define an app named myapp in two different YAML files, Upsun only takes the second one into account.
Note that source.root (and any other .upsun/app.yaml parameters) will not be included in the final configuration.
# Activity scripts [Utility routines](https://docs.upsun.com/integrations/activity/utility.html)
The following utility routines can help simplify common tasks in your activity scripts. They’re free to copy, modify, bend, fold, spindle, and mutilate as needed for your own scripts. They also demonstrate some common patterns for working with the activity and project data structures.
## Route access
```javascript
/**
* Returns just those routes that point to a valid upstream.
*
* This method is similar to routes(), but filters out redirect routes that are rarely
* useful for app configuration. If desired it can also filter to just those routes
* whose upstream is a given application name. To retrieve routes that point to the
* current application where the code is being run, use:
*
* routes = getUpstreamRoutes(applicationName);
*
* @param {string} [appName]
* The name of the upstream app on which to filter, if any.
* @return {object}
* An object map of route definitions. The generated URLs of the routes are added as a "url" key.
*/
function getUpstreamRoutes(appName) {
return Object.entries(activity.payload.deployment.routes).reduce(
(upstreams, [url, route]) =>
route.type === "upstream" &&
(!appName || appName === route.upstream.split(":")[0])
? {
...upstreams,
[url]: {
...route,
url,
},
}
: upstreams,
{}
);
}
```
```javascript
/**
* Returns the primary route.
*
* The primary route is the one marked primary in `.upsun/config.yaml`, or else
* the first non-redirect route in that file if none are marked.
*
* @return {object}
* The route definition. The generated URL of the route is added as a "url" key.
*/
function getPrimaryRoute() {
return Object.entries(activity.payload.deployment.routes).reduce(
(primary, [url, route]) =>
route.primary
? {
...route,
url,
}
: primary,
{}
);
}
```
```javascript
/**
* Returns the route definition that has the specified id.
*
* Note: If no route ID was specified in .upsun/config.yaml then it will not be possible
* to look up a route by ID.
*
* @param {string} id
* The ID of the route to load.
* @return {object}
* The route definition. The generated URL of the route is added as a "url" key.
* @throws {Error}
* If there is no route by that ID, an exception is thrown.
*/
function getRoute(id) {
const found = Object.entries(activity.payload.deployment.routes).reduce(
(foundRoute, [url, route]) =>
route.id === id
? {
...route,
url,
}
: foundRoute,
null
);
if (found === null) {
throw new Error(`No such route id found: ${id}`);
}
return found;
}
```
# Integrations [Health notifications](https://docs.upsun.com/integrations/notifications.html)
Upsun can notify you when various events happen on your project, in any environment. At this time the only notification provided is a low disk space warning, but others may be added in the future.
To add or modify an integration for a project, you need to be a [project admin](../administration/users.md#project-roles).
## Default low-disk email notifications
When you create a new project,
Upsun creates a default [low-disk email notification](#low-disk-warning) for all [project admins](../administration/users.md#project-roles).
## Available notifications
### Low-disk warning
Upsun monitors disk space usage on all applications and services in your cluster.
* When available disk space drops below 20% or 4 GB, whichever is smaller, a warning notification is generated.
* When available disk space drops below 10% or 2 GB, whichever is smaller, a critical notification is generated.
* When available disk space returns above 20% or 4 GB, whichever is smaller, an all-clear notification is generated.
Notifications are generated every 5 minutes, so there may be a brief delay between when the threshold is crossed and when the notification is triggered.
## Configuring notifications
Health notifications can be set up via the [Upsun CLI](/administration/cli/_index.md), through a number of different channels.
### Email notifications
A notification can trigger an email to be sent, from an address of your choosing to one or more addresses of your choosing.
You can view an email notification by running `upsun integration:get`.
```bash
upsun integration:get
+--------------+---------------+
| Property | Value |
+--------------+---------------+
| id | abcdefghijklm |
| type | health.email |
| role | |
| from_address | |
| recipients | - '#admins' |
+--------------+---------------+
```
To edit the `recipients` that receive the default email notification, use the `integration:update` command.
```bash
upsun integration:update abcdefghijklm --recipients you@example.com
```
The `recipients` field may be any valid email address, or one of the following special values.
* `#admins` maps to all project admins and up.
* `#viewers` maps to everyone with access to the project.
To add a new email notification, register a `health.email` integration as follows:
```bash
upsun integration:add --type health.email --recipients them@example.com --recipients others@example.com
```
You must specify one or more `recipients`, each as its own switch.
The default `from-address` points to the "Upsun Bot".
You can also configure a custom `--from-address`. The `--from-address` is whatever address you want the email to appear to be from. It is completely fine to use the same email address for both `from-address` and `recipients`. Note that depending on the configuration of the recipient mail server (including SPF and DKIM DNS entries) when using a custom `from-address`, the email can be marked as spam or lost.
### Slack notifications
A notification can trigger a message to be posted to a Slack channel via a [Slack app](https://api.slack.com/apps).
#### 1. Optional: Create a Slack app
1. Open the [Slack API website](https://api.slack.com/) and go to **Your apps**.
2. Click **Create an App**.
3. Choose if you want to build your app from scratch, or via [an app manifest](https://api.slack.com/concepts/manifests).
4. Give your app a name.
5. Select a workspace to install your app in.
Note
If you are not an admin of the selected workspace, request approval to install your app there.
6. Click **Create App**.
#### 2. Enable notifications
1. Open the [Slack API website](https://api.slack.com/) and go to **Your apps**.
2. Go to **Features** > **OAuth & Permissions** in the sidebar.
3. Scroll down to the **Scopes** area and select **User Token Scopes**.
4. Click **Add an OAuth Scope** to add the `chat:write` scope.

5. Go to **Settings** > **Install app** in the sidebar.
Note
If you are not an admin of the workspace, you need to provide a link to install the app into the workspace and onto a channel.
Once the app is approved and installed, a User OAuth Token is provided in your app settings.
Copy the token, and use it in the next step.
6. Using the **User OAuth Token**, run the following command:
```bash
upsun integration:add --type health.slack --token USER_OAUTH_TOKEN --channel CHANNEL_NAME --project PROJECT_ID
```
For example, if you want your Slack app to post messages in the `project-notifications` channel, write the channel name in the command as you would reference it within Slack:
```bash
upsun integration:add --type health.slack ... --channel '#project-notifications' ...
```
6. When the integration is successfully configured, Upsun then sends an initial message to the channel.
Bot users v. Slack apps
Previously, Upsun allowed for the configuration of health notifications sent to Slack via bot users and their associated API tokens.
As of June 2024, Slack has deprecated bot users, and integrations must be configured using Slack apps as described above.
If you already have defined an integration using a bot user API token, it will continue to work properly, though you should consider upgrading your processes to the above settings to avoid any future retirement.
### PagerDuty notifications
A notification can trigger a message to be sent via PagerDuty, if you are using that service.
First, create a new PagerDuty "[integration](https://support.pagerduty.com/docs/services-and-integrations)" that uses the Events API v2.
Copy the "Integration Key" as known as the "routing key" for the integration.
Now register a `health.pagerduty` integration as follows:
```bash
upsun integration:add --type health.pagerduty --routing-key YOUR_ROUTING_KEY
```
Any notification will now trigger an alert in PagerDuty.
## Validate the integration
You can then verify that your integration is functioning properly [using the CLI](/integrations/overview.md#validate-integrations) command
```bash
upsun integration:validate
```
# Administration [Organizations](https://docs.upsun.com/administration/organizations.html)
Organizations allow you to manage your Upsun projects, users, and billing.
You can group multiple projects in one organization and manage them together.
To manage users within your organization, see how to [manage organization users](./users.md#manage-organization-users).
## Manage your organization settings
As an organization owner, you can manage the basic settings for your organization such as its name and URL.
Navigate to the organization you want to manage (or a project in it).
Open the user menu (your name or profile picture).
Click Settings.
Click Edit to edit the label or click in the Organization URL field to edit the URL.
Click Save.
To change the name (URL) and label of the acme organization, run:
upsun organization:info --org acme label "Acme Corp" name acme-corp
To verify the changes, run:
upsun organization:info --org acme-corp
## Manage your organization billing
As an organization owner or an organization user with the **Manage billing** permission,
you can access and download invoices and edit billing information such as the stored credit card and billing address.
Navigate to the organization you want to manage (or a project in it).
Open the user menu (your name or profile picture).
Click Billing.
## Create a new organization
When you create a new project, if you don't already have an organization, one is created for you automatically.
You can create new organizations with different payment methods and billing addresses
and organize your projects as you want.
To monitor your spend, you can set billing alerts on your new organization.
Billing alerts are based on a current month estimate.
Once that estimate reaches a defined threshold, you receive an email notification.
## Delete an existing organization
As an organization owner, you can delete your own organization.
Note that if your organization owns projects or owes remaining invoices, you can not delete it yourself.
To have it deleted, [contact support](/learn/overview/get-support.md).
Navigate to your existing organization or a project in it.
Open the user menu (your name or profile picture).
Click Settings.
Click Delete Organization.
Confirm your decision by clicking Delete.
To delete the organization acme, run:
upsun organization:delete --org acme
## Transfer project ownership
You can transfer your plan ownership to a different organization at anytime.
You have to be an organization owner or have the [manage plan permission](./users.md#organization-permissions).
1. Make the new organization owner a [project admin](./users.md#)
for the project you want to transfer.
2. To ask for the transfer, from your organization account open a [support ticket](/learn/overview/get-support).
Once the transfer is completed, the new organization can administer all project settings and billing and receives future invoices.
Ownership transfer automatically transfers subscription charges to the new organization.
## Transfer organization ownership
To transfer an organization to a different owner, first make sure that user is part of the organization.
If they aren't yet, [add them](./users.md#add-a-user-to-an-organization).
Then open a [support ticket](/learn/overview/get-support) from the current organization to ask for the transfer.
# Administration [Administer teams](https://docs.upsun.com/administration/teams.html)
Organizations on Upsun are made up of both [projects](/projects/) and [users](/administration/users.md).
While organizations by themselves allow you to assign project and environment type permissions to individual users on individual projects,
having many users and many projects calls for another method to group common access control settings.
**Teams** provide a grouping that connects a subset of an organization's users to another subset of that organization's projects.
That relationship enables organization owners to set default project and environment type access settings for each user and project from one place.
There is no limit to the number of teams that can be defined within a single organization.
## Create a new team
As an organization owner or member with **Manage users** permissions,
you can create new teams.
Teams must belong to an organization, so [create one](/administration/organizations.md#create-a-new-organization) first.
You can create new organizations with different payment methods and billing addresses
and organize your projects as you want, but keep in mind that both users and teams are restricted to single organizations.
Open the user menu (your name or profile picture).
Select Teams from the dropdown.
Click + Create team.
Enter the information for your team. Only the team name is required at this point, but you can define environment type permissions now if you’d like.
Click Create team.
Run the following command:
upsun team:create -o ORGANIZATION_NAME
Enter a team name.
Define your team’s project role (admin or viewer).
If your team has viewer rights on the project, define its role on each type of environment.
Enter Y to confirm.
Note
To view a list of all the existing teams in your organization, run the following command:
upsun team:list -o ORGANIZATION_NAME
## Delete an existing team
As an organization owner or member with **Manage users** permissions,
you can delete existing teams.
Note that deleting teams and deleting users are not equivalent.
Deleting a team will remove member access permissions to projects described by the team,
but it will _not_ [remove users from the organization](/administration/users.md#remove-a-user-from-an-organization) (or your billing).
Open the user menu (your name or profile picture).
Select Teams from the dropdown.
Find the team you want to delete under the Manage teams list,
then click More.
Click Delete team.
Click Yes to confirm.
Run the following command:
upsun team:delete -o ORGANIZATION_NAME
Select the team you want to delete.
Enter Y to confirm.
## Manage team settings
As an organization owner or member with **Manage users** permissions,
you can manage the settings of existing teams such as:
- [It's name](#team-name)
- [The environment type permissions granted to members on individual projects](#project--environment-type-permissions)
- [Team members](#team-members)
- [Project access](#team-access-to-projects)
### Team name
Open the user menu (your name or profile picture).
Select Teams from the dropdown.
Find the team you want to rename under the Manage teams list,
then click More.
Click Edit team.
In the sidebar click the Edit link, and edit the team name.
Click Save.
Run the following command:
upsun team:update -o ORGANIZATION_NAME
Select the team you want to rename.
Enter the new name.
Confirm or adjust the team permissions.
Enter Y to confirm.
### Project & environment type permissions
The primary purpose of teams is to allow organizations to quickly apply, audit, and update project and environment type permissions for groups of users.
Open the user menu (your name or profile picture).
Select Teams from the dropdown.
Find the team you want to modify under the Manage teams list,
then click More.
Click Edit team.
In the sidebar, you can:
Assign Project permissions by selecting the check box to make team members Project admins of every project added to the team.
Assign Environment type permissions by using the dropdowns to grant No access, Viewer, Contributor, or Admin rights to team members for Production, Staging, and Development project environment types.
Click Save.
Run the following command:
upsun team:update -o ORGANIZATION_NAME
Select the team whose permissions you want to update.
Confirm or adjust the team name.
Adjust the team permissions.
Enter Y to confirm.
### Team members
#### Add users to a team
To join a team, a user must already have been added [to the organization](/administration/users.md#manage-organization-access),
where their [organization permissions](/administration/users.md#organization-permissions) are defined.
Open the user menu (your name or profile picture).
Select Teams from the dropdown.
Find the team you want to modify under the Manage teams list,
then click More.
Click Add user.
Locate and select organization users from the dropdown.
In the sidebar click the Edit link, and edit the team name.
Click Add users.
Run the following command:
upsun team:user:add -o ORGANIZATION_NAME
Select the team you want to add a user to.
Enter the user’s email address.
Enter Y to confirm.
Note
To view a list of all the users on a team, follow these steps:
Run the following command:
upsun team:user:list -o ORGANIZATION_NAME
Select the team whose users you want to display.
#### Remove users from a team
Note that deleting users from teams and deleting users from organizations are not equivalent.
Deleting users from a team will remove member access permissions to projects described by the team,
but it will _not_ [remove users from the organization](/administration/users.md#remove-a-user-from-an-organization) (or your billing).
Option 1: Remove projects from a team with from Team settings
Navigate to your existing organization.
Open the user menu (your name or profile picture).
Select Teams from the dropdown.
Find the team you want to modify under the Manage teams list,
then click More.
Click Edit team.
Find the project you want to modify under the PROJECTS tab view,
then click More.
Click Remove project.
Select All projects, or choose individual projects from the dropdown.
Click Yes to confirm.
Option 2: Remove teams from a project from project’s Access settings
Navigate to your existing organization.
Select the project you want to add to the existing team.
Navigate to the project’s settings by clicking the Settings icon.
Click Access settings under Project settings in the sidebar.
Find the team under the TEAMS tab view,
then click More.
Click Remove team.
Click Yes to confirm.
Run the following command:
upsun team:project:delete -o ORGANIZATION_NAME
Select a team.
Select the project whose access you want to revoke for the team.
Enter Y to confirm.
# Administration [Administer users](https://docs.upsun.com/administration/users.html)
Upsun offers very granular and flexible user permissions across projects and organizations.
When a user is added to a project, they are automatically added to your organization.
## Manage project access
If you have set up an external integration to GitHub, GitLab, or Bitbucket and your users can't clone the project locally,
see how to [troubleshoot source integrations](../integrations/source/troubleshoot.md).
### Project roles
A user can have one of the following roles to control their access at project level:
| Role | View environment | Push code | Manage user access | Change settings | Execute actions on all environments |
|----------------|------------------|-----------|--------------------|-----------------|-------------------------------------|
| Project admin | Yes | Yes | Yes | Yes | Yes |
| Project viewer | Yes | No | No | No | No |
By default, organization owners have **Project admin** access on all of the projects within their organization.
### Environment type roles
An environment type (Production, Staging, and Development) groups one or more environments together so that you can manage access for all environments of that type:
- A role assigned to an environment type applies to all environments of that type.
- Only one environment per project can be of the type: Production.
It is set automatically as the default branch and can't be overridden separately.
- You can change an environment's type (except for the Production environment).
- You can have multiple preview (staging and development) environments.
A user can have one of the following roles on an environment type which grants them permissions on all environments of this type:
| Role | View environment | Force push | Push code | Branch environment | SSH access | Change settings | Execute actions |
|-------------|------------------|------------|-----------|--------------------|------------|-----------------|-----------------|
| Admin | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
| Contributor | Yes | No | Yes | Yes | Yes | No | No |
| Viewer | Yes | No | No | Yes | No | No | No |
To customize which roles can use SSH, set [`access` in your app configuration](/create-apps/app-reference/single-runtime-image.md#access).
### View a user's permissions across all of the projects in your organization
For each user, you can view a summary of their roles and permissions
across all projects in your organization.
For example, if you want to add user1@example.com to the project as a project admin,
run the following command:
upsun user:add user1@example.com -r admin
If you want to add user2@example.com to the project as a contributor for Development environments
and a viewer for Staging environments,
run the following command:
Select the project where you want to add a new user.
Click Settings.
Click Access.
Click + Add.
Add the user’s details and choose their permissions.
Click Save.
The user has to create an account before they can access the project.
Once you add a user to a project, they receive an invitation email with instructions.
To apply SSH access changes after you add a user to a project,
[trigger a redeploy](../development/troubleshoot.md#force-a-redeploy).
### Manage project users
To manage user permissions on a project, you need to be a [project admin](#project-roles),
be an organization owner, or have the [**Manage users** permission for the organization](#organization-permissions).
To change user permissions, follow these steps:
Select the project where you want to update user access.
Click Settings.
Click Access.
Click the user you want to update permissions for.
Update environment type permissions, or click Remove user.
Click Accept.
To apply SSH access changes after you add a remove a user from a project or environment type,
[trigger a redeploy](../development/troubleshoot.md#force-a-redeploy).
### Remove a user from a project
To remove a user from a project, you need to be a [project admin](#project-roles),
be an organization owner, or have the [**Manage users** permission for the organization](#organization-permissions).
To remove a user, follow these steps:
Open the user menu (your name or profile picture).
Click Users.
For the user you want to remove, click More.
For the project you want to remove them from, click More.
Click Remove from project.
Click Yes.
To apply SSH access changes after changing a user's permissions for an environment type,
[trigger a redeploy](../development/troubleshoot.md#force-a-redeploy).
## Manage organization access
All users who are added to any project within an organization become members of that organization.
By default, such users have no [organization permissions](#organization-permissions).
You can also have organization users who aren't part of any projects.
Users who are a part of an organization with the **List projects** permission can see all projects in that organization at the organization's URL,
which takes the form `https://console.upsun.com/ORGANIZATION_NAME`.
They can only access projects they've been explicitly invited to.
For more information on project access control, see how to [manage project users](#manage-project-users).
### Organization permissions
As an organization owner or an organization user with the **Manage users** permission,
you can invite other users to your organization and grant them the following permissions:
- **Manage billing** (`billing`):
Add, remove, and edit billing information.
Access invoices and vouchers.
Users with this permission receive monthly invoices by email.
- **Manage plans** (`plans`):
Access to update settings of existing projects in an organization.
- **Manage users** (`members`):
Add, remove, and edit organization-level users and permissions, except their own.
Users with this permission can't grant other users permissions that they themselves don't have.
- **Create projects** (`projects:create`):
Create new projects within the organization.
- **List projects** (`projects:list`):
See all projects in an organization, even those the user can't access.
Note
Users with the Manage users (members) permission can add, edit, or remove any user’s permissions except their own.
Users with the Manage billing (billing) permission automatically are granted List projects (projects:list) permission.
That is, they are able to see all organization projects once given billing rights.
Users without any of these permissions can only access [projects where they're users](#project-roles).
They can't access or manage the rest of the organization.
Organization owners have all permissions within their organization.
Their permission level can't be edited.
Organization owners can't be removed from their organization,
except through an [ownership transfer](../administration/organizations.md#transfer-project-ownership).
### Add a user to an organization
For example, to update the permissions for alice@example.com in your acme organization
so that she has only the Manage billing permission, run the following command:
Navigate to the organization you want to manage (or a project in it).
Open the user menu (your name or profile picture).
Click Users.
Next to the user you want to remove, click More.
Click Remove from organization.
To delete users in bulk, select the users to remove and click Remove users from organization.
Remove a user from an organization will remove them from all projects they were a member of.
# Billing [Administer your billing](https://docs.upsun.com/administration/billing/billing-admin.html)
The [Console](/administration/web/_index.md) is where you can keep your billing details up to date and redeem your vouchers.
## Manage your billing details
To add or edit billing details for your organization, follow these steps:
1. Navigate to your organization.
2. Open the user menu (your name or profile picture).
3. Click **Billing**.
4. Open the **Billing details** tab.
5. Add or update your billing details and click **Save**.
6. Add or update your payment method and click **Submit**.
## Redeem a voucher
To redeem a voucher, follow these steps:
1. Navigate to your organization.
2. Open the user menu (your name or profile picture).
3. Click **Billing**.
4. Open the **Vouchers** tab.
5. Enter your voucher code.
6. Click **Redeem**.# Command line interface (CLI) [Authenticate the CLI using an API token](https://docs.upsun.com/administration/cli/api-tokens.html)
You need to set up an API token to authenticate the Upsun CLI for any of the following tasks:
- Running automated tasks on a CI system
- Running automated tasks directly on app container, for example in a cron job
## Before you begin
You might need the [Upsun CLI](../cli/_index.md) to perform certain tasks.
For example, you need the CLI to do the following:
- [Check the validity of an API token](#optional-check-the-validity-of-your-api-token).
- [Load the CLI SSH certificate for non-CLI commands](#use-the-cli-ssh-certificate-for-non-cli-commands).
## 1. Create a machine user
To safely run automated tasks, first create machine users.
Each machine user has its own Upsun account associated with a unique email address.
You can grant them restrictive [access permissions](../users.md) to handle specific automated tasks.
For security purposes, create a machine user for each type of task you want to automate.
To create a machine user, follow these steps:
This sets your machine user as a viewer on your project and a contributor on development environments,
with no access to other environment types.
Note that you can further adjust user roles depending on your needs and each environment type.
In the email invitation, click Create account.
To create a Upsun account for the machine user, click Sign up and follow the instructions.
Go to your project and click Settings.
In the Project Settings menu, click Access.
Click Add.
Enter your machine user’s email address.
For each environment type, assign a role to your machine user and click Save.
## 2. Create an API token
1. Log in to the Console as your machine user.
2. Open the user menu (your name or profile picture).
3. Click **My profile**.
4. Go to the **API tokens** tab and click **Create API token**.
5. Enter a name for your API token and click **Create API token**.
6. To copy the API token to your clipboard, click ** Copy**.
Note that after you close the **API tokens** tab, you can't display the API token again.
7. Store the API token somewhere secure on your computer.
### Optional: check the validity of your API token
To check that your API token is valid, run the following command:
```bash
upsun auth:api-token-login
```
When prompted, enter your API token.
You get output similar to this:
```bash
The API token is valid.
You are logged in.
```
For security reasons, rotate your API tokens regularly.
When an API token is compromised, revoke it immediately.
## 3. Authenticate the CLI using your API token
After you create your API token, you can use it to do the following:
- Allow a CI system to run automated tasks using the Upsun CLI.
- Run automated tasks on an app container using the Upsun CLI,
for example in a cron job.
Note that when running CLI commands in these cases,
some operations might take time to complete.
To avoid waiting for an operation to complete before moving on to the next one,
use the `--no-wait` flag.
### Authenticate in a CI system
You can allow your CI system to run automated tasks using the Upsun CLI.
To do so, create an environment variable named `UPSUN_CLI_TOKEN` with your API token as its value.
For more information, see your CI system's official documentation.
To run SSH-based commands that aren't specific to the Upsun CLI,
see how to [load the proper SSH certificate](#use-the-cli-ssh-certificate-for-non-cli-commands).
### Authenticate in an environment
You can run automated tasks on an app container using the Upsun CLI.
To do so, set your API token as a [top-level environment variable](../../development/variables/_index.md#top-level-environment-variables).
Open the environment where you want to add the variable.
Click Settings.
Click Variables.
Click + Add variable.
In the Variable name field, enter env:UPSUN_CLI_TOKEN.
In the Value field, enter your API token.
Make sure the Available at runtime and Sensitive variable options are selected.
Click Add variable.
Then add a build hook to your app configuration to install the CLI as part of the build process.
```yaml {configFile="app"}
hooks:
build: |
set -e
echo "Installing Upsun CLI"
curl -fsSL https://raw.githubusercontent.com/platformsh/cli/main/installer.sh | bash
echo "Testing Upsun CLI"
upsun
```
You can now call the CLI from within the shell on the app container or in a cron job.
To run SSH-based commands that aren't specific to the Upsun CLI,
see how to [load the proper SSH certificate](#use-the-cli-ssh-certificate-for-non-cli-commands).
You can set up a cron job on a specific type of environment.
For example, to run the `update` source operation on your production environment,
use the following cron job:
```yaml
crons:
update:
spec: '0 0 * * *'
commands:
start: |
if [ "$PLATFORM_ENVIRONMENT_TYPE" = production ]; then
upsun backup:create --yes --no-wait
upsun source-operation:run update --no-wait --yes
fi
```
## Use the CLI SSH certificate for non-CLI commands
When you set a `UPSUN_CLI_TOKEN` environment variable,
the CLI authentication isn't complete until your run a CLI command
or load the CLI SSH certificate.
For example, after setting a `UPSUN_CLI_TOKEN` environment variable,
you might need to run `ssh`, `git`, `rsync`, or `scp` commands before you run any CLI commands.
In this case, to ensure all your commands work, load the CLI SSH certificate first.
To do so, run the following command:
```bash
upsun ssh-cert:load --no-interaction
```
# Tutorials [Automate your code updates](https://docs.upsun.com/learn/tutorials/dependency-updates.html)
Upsun allows you to update your dependencies through [source operations](/create-apps/source-operations.md).
## Before you start
You need:
- The [Upsun CLI](/administration/cli/_index.md)
- An [API token](/administration/cli/api-tokens.md#2-create-an-api-token)
## 1. Define a source operation to update your dependencies
To facilitate updating your dependencies in your project,
define a source operation in your `.upsun/config.yaml` file
depending on your dependency manager:
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"source:operations:update:command:| set -e
composer update
git add composer.lock
git add -A
git diff-index --quiet HEAD || git commit --allow-empty -m "Update Composer dependencies"
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"source:operations:update:command:| set -e
npm update
git add package.json package-lock.json
git add -A
git diff-index --quiet HEAD || git commit --allow-empty -m "Update npm dependencies"
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"source:operations:update:command:| set -e
yarn upgrade
git add yarn.lock
git add -A
git diff-index --quiet HEAD || git commit --allow-empty -m "Update yarn dependencies"
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"source:operations:update:command:| set -e
go get -u
go mod tidy
git add go.mod go.sum
git add -A
git diff-index --quiet HEAD || git commit --allow-empty -m "Update Go dependencies"
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"source:operations:update:command:| set -e
pipenv update
git add Pipfile Pipfile.lock
git add -A
git diff-index --quiet HEAD || git commit --allow-empty -m "Update Python dependencies"
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"source:operations:update:command:| set -e
bundle update --all
git add Gemfile Gemfile.lock
git add -A
git diff-index --quiet HEAD || git commit --allow-empty -m "Update Ruby dependencies"
## 2. Automate your dependency updates with a cron job
After you've defined a source operation to [update your dependencies on your project](#1-define-a-source-operation-to-update-your-dependencies),
you can automate it using a cron job.
Note that it’s best not to run source operations on your production environment,
but rather on a dedicated environment where you can test changes.
Make sure you have the [Upsun CLI](/administration/cli/_index.md) installed
and [an API token](/administration/cli/api-tokens.md#2-create-an-api-token)
so you can run a cron job in your app container.
1. Set your API token as a top-level environment variable:
Open the environment where you want to add the variable.
Click Settings.
Click Variables.
Click + Add variable.
In the Variable name field, enter env:UPSUN_CLI_TOKEN.
In the Value field, enter your API token.
Make sure the Available at runtime and Sensitive variable options are selected.
Click Add variable.
Note
Once you add the API token as an environment variable,
anyone with SSH access can read its value.
Make sure you carefully check your user access on this project.
2. Add a build hook to your app configuration to install the CLI as part of the build process:
```yaml {configFile="app"}
applications:
myapp:
hooks:
build: |
set -e
echo "Installing Upsun CLI"
curl -fsSL https://raw.githubusercontent.com/platformsh/cli/main/installer.sh | bash
echo "Testing Upsun CLI"
upsun
```
3. Then, to configure a cron job to automatically update your dependencies once a day,
use a configuration similar to the following:
```yaml {configFile="app"}
applications:
myapp:
# ...
crons:
update:
# Run the code below every day at midnight.
spec: '0 0 * * *'
commands:
start: |
set -e
upsun sync -e development code data --no-wait --yes
upsun source-operation:run update --no-wait --yes
```
The example above synchronizes the `development` environment with its parent
and then runs the `update` source operation defined [previously](#1-define-a-source-operation-to-update-your-dependencies).
## 3. Configure notifications about dependency updates
To get notified every time a source operation is triggered and therefore every time a dependency is updated,
you can configure activity scripts or webhooks.
### Notifications through an activity script
After you've defined a source operation to [update your dependencies on your project](#1-define-a-source-operation-to-update-your-dependencies),
you can configure an activity script
to receive notifications every time a dependency update is triggered.
Example
You want to get notified of every dependency update
through a message posted on a Slack channel.
To do so, follow these steps:
In your Slack administrative interface, create a new Slack webhook.
You get a URL starting with https://hooks.slack.com/.
Replace SLACK_URL in the following .js script with your webhook URL.
Add the following code to a .js file:
/**
* Sends a color-coded formatted message to Slack.
*
* To control what events trigger it, use the --events switch in
* the Upsun CLI.
*
* Replace SLACK_URL in the following script with your Slack webhook URL.
* Get one here: https://api.slack.com/messaging/webhooks
* You should get something like: const url = 'https://hooks.slack.com/...';
*
* activity.text: a brief, one-line statement of what happened.
* activity.log: the complete build and deploy log output, as it would be seen in the Console log screen.
*/functionsendSlackMessage(title,message){consturl='SLACK_URL';constmessageTitle=title;constcolor=activity.result==="success"?"#66c000":"#ff0000";constbody={attachments:[{title:messageTitle,text:message,color:color,},],};constresp=fetch(url,{method:"POST",headers:{"Content-Type":"application/json",},body:JSON.stringify(body),});if(!resp.ok){console.log("Sending slack message failed: "+resp.body.text());}}sendSlackMessage(activity.text,activity.log);
Optional: to only get notifications about specific environments,
add the following flag to the command: --environments=your_environment_name.
Anytime a dependency is updated via a source operation,
the activity script now reports it to Slack.
### Notifications through a webhook
After you've defined a source operation to [update your dependencies on your project](#1-define-a-source-operation-to-update-your-dependencies),
you can configure a webhook to receive notifications every time a dependency update is triggered.
[Webhooks](/integrations/activity/webhooks.md) allow you to host a script yourself externally.
This script receives the same payload as an activity script and responds to the same events,
but can be hosted on your own server and in your own language.
To configure the integration between your webhook and your source operation,
run the following [Upsun CLI](/administration/cli/_index.md) command:
```bash
upsun integration:add --type=webhook --url=URL_TO_RECEIVE_JSON --events=environment.source-operation
```
Optional: to only get notifications about specific environments,
add the following flag to the command: `--environments=your_environment_name`.
To test the integration and the JSON response,
you can generate a URL from a service such as [webhook.site](https://webhook.site)
and use the generated URL as `URL_TO_RECEIVE_JSON`.
This URL then receives the JSON response when a source operation is triggered.
Anytime a dependency is updated via a source operation,
the webhook now receives a POST message.
This POST message contains complete information about the entire state of the project at that time.
# Console [Configure a project](https://docs.upsun.com/administration/web/configure-project.html)
Each project has settings that apply to everything within that project, including all its environments.
You can only see and update settings for projects where you are a [Project Admin](../users.md).
To access the settings, click **Settings** from the main project page.
The settings are divided into several sections.
## General
The **General** section shows you the project's region and allows you to update the project name and [timezone](../../projects/change-project-timezone.md).

## Access
The **Access** section allows you to [manage user access to the project](../users.md).

## Certificates
The **Certificates** section shows a list of your project's TLS certificates.
To see details about a certificate or delete one, click **Edit **.
See how to [add custom certificates](../../domains/steps/tls.md).

## Domains
The **Domains** section allows you to manage the domains where your project is accessible.
See how to [set up your domain](../../domains/steps/_index.md).

## Deploy Key
The **Deploy Key** section shows you the public SSH key you can add to your private repositories.
Adding it lets Upsun access the repositories during the build process.
This is useful if you want to reuse some code components across multiple projects and manage those components as dependencies of your project.

## Integrations
The **Integrations** section allows you to manage all of your [integrations](../../integrations/_index.md).

## Variables
The **Variables** section allows you to manage all project-wide [variables](../../development/variables/_index.md).

# JavaScript/Node.js [Debugging](https://docs.upsun.com/languages/nodejs/debug.html)
Note
You can now use composable image (BETA) to install runtimes and tools in your application container. To find out more, see the dedicated documentation page.
Effectively debugging web apps takes effort,
especially when an HTTP request goes through multiple layers before reaching your web app.
Follow the steps below to debug a specific app.
You can choose to debug in an environment deployed to Upsun
or with your app running locally but connected to deployed services.
In either case, make sure to debug in a preview environment.
For more general information, see how to [troubleshoot development](/development/troubleshoot).
## 1. Create a new environment
Start by creating a new environment completely isolated from production but with the same data for debugging:
```bash
upsun branch debug-branch
```
## 2. Get access
Stop the current process and restart it in inspect mode:
sv stop app
node --inspect <START_FILE>
In the same terminal as the previous step, run the following command:
node --inspect <START_FILE>
Replace `` with the file defined for [your app's `start` command](./_index.md#4-start-your-app).
You get output something like this:
```bash
Debugger listening on ws://127.0.0.1:9229/10701e5d-d627-4180-a967-d47a924c93c0
For help, see: https://nodejs.org/en/docs/inspector
Listening on port 8888
```
## 4. (If debugging remotely) Forward the debugger port locally
In another terminal, create an SSH tunnel that forwards to the 9229 port:
```bash
ssh -N -L 9229:localhost:9229 $(upsun ssh --pipe)
```
## 5. Connect the debugger
You can now connect the debugger as if you were debugging a local application.
See examples with some common tools:
Now when you load the site at your deployed URL (if debugging remote) or localhost (if debugging locally),
the local debugger you've attached is called.
Set breakpoints:
In the JavaScript files from your remote site:
On the Run and Debug tab under Loaded Scripts find Attach: Remote Process > /app.
Directly in your source files.
## Other issues
### pm2 process manager blocks other processes
If you're using the [`pm2` process manager](https://github.com/unitech/pm2) to start your app from a script,
you might find it daemonizes itself and blocks other processes (such as backups) by constantly respawning.
This may happen even if you use the `--no-daemon` flag.
Instead of using a script, call `pm2 start` directly in your [`start` command](./_index.md#4-start-your-app).
# Set up a custom domain [DNS management and apex domains](https://docs.upsun.com/domains/steps/dns.html)
Using `CNAME` records helps [prevent downtime](#cname-records) during maintenance operations.
But `CNAME` records can't point to apex domains,
so you need to [set up a workaround](#workarounds-for-apex-domains).
Available workarounds depend on your DNS provider.
## `CNAME` records
Each site on Upsun is made up of a set of containers.
To map incoming requests to the appropriate container,
Upsun runs routers in [each region](../../development/regions.md).
A router's IP address can change in two cases:
- During an upgrade or maintenance operation, routers can be taken offline while changes are applied.
- During a region upscale or downscale, routers can be added or removed.
In such situations, using `A` records can cause downtime.
`A` records map a domain to an IP address.
When a router's IP address changes,
you need to manually update your `A` records.
Your site remains offline until you do,
or until the router is back from maintenance.
To prevent downtime, create `CNAME` records through your DNS provider.
`CNAME` records map a domain to another.
Set up your `CNAME` records to point at your project's [target URL](../../domains/steps/_index.md#1-get-the-target-for-your-project).
The DNS record for this target URL automatically resolves to the IP addresses of the routers in your project's region.
When a router's IP address changes,
the DNS record is automatically and immediately updated.
This prevents downtime without intervention from you.
Note that `CNAME` records can't point to [apex domains](/glossary.md#apex-domain).
Check with your DNS provider if they offer [workarounds](#workarounds-for-apex-domains).
## Workarounds for apex domains
Although `CNAME` records can't point to apex domains,
most DNS providers offer workarounds.
Contact your DNS provider and choose the option that works for you.
If you use a CDN, you likely already have a workaround in place,
such as with [Fastly](../cdn/fastly.md#3-handle-apex-domains)
and [Cloudflare](../cdn/cloudflare.md#3-handle-apex-domains).
### Custom records
Some DNS providers offer custom records such as `ANAME`, `ALIAS` or `HTTPS` records,
which you can manage like `CNAME` records.
But unlike `CNAME` records, these custom records can point to apex domains.
To use custom records, follow the instructions on [how to set up a custom domain](./_index.md).
When you come to configuring your DNS provider, instead of a `CNAME` record,
add a custom record pointing from your domain to [your project's target URL](https://docs.platform.sh/domains/steps.html#2-get-the-target-for-your-project).
### Domain forwarding
If your DNS provider doesn't support custom records,
consider using domain forwarding.
If your domain is `example.com`, domain forwarding redirects all requests from `example.com` to `www.example.com`.
To use domain forwarding, follow these steps:
1. Make the `www.` version of your site the default (canonical) version
and configure your app and routes to [use the `www` subdomain as `upstream`](../../define-routes/_index.md).
2. Follow the instructions on [how to set up a custom domain](./_index.md).
When you come to configuring your DNS provider,
instead of a `CNAME` record, add a record forwarding requests
from `YOUR_DOMAIN` to `www.YOUR_DOMAIN`.
### Redirection service
If your DNS provider doesn't support custom records or domain forwarding,
consider using a redirection service.
If your domain is `example.com`,
a redirection service uses an `A` record to redirect all requests from `example.com` to `www.example.com`.
To use a redirection service, follow these steps:
1. Make the `www.` version of your site the default (canonical) version
and configure your app and routes to [use the `www` subdomain as `upstream`](../../define-routes/_index.md).
2. Follow the instructions on [how to set up a custom domain](./_index.md).
When you come to configuring your DNS provider, instead of a `CNAME` record,
add an `A` record pointing from your domain to the redirection service.
### `A` records
If your DNS provider doesn't support any other workaround,
consider using `A` records, but only as a last resort.
When you use `A` records, [if a router's IP address changes](#cname-records),
you need to update your `A` records manually.
Until you do, your site can appear offline because requests are lost.
To use `A` records, follow these steps:
1. [Get the IP addresses](/development/regions.md#public-ip-addresses) of your project's production environment.
2. Follow the instructions on [how to set up a custom domain](./_index.md).
When you come to configuring your DNS provider, instead of a `CNAME` record,
add `A` records pointing from your domain to each of the IP addresses from step 1.
When a request comes in, one of those IP addresses is used at random.
# PHP [Extensions](https://docs.upsun.com/languages/php/extensions.html)
Note
You can now use the Upsun composable image (BETA) to install runtimes and tools in your application container.
When using the composable image, see how you can:
PHP has a number of [extensions](https://pecl.php.net/) developed by members of the community.
Some of them are available for Upsun containers.
You can define the PHP extensions you want to enable or disable:
```yaml {configFile="app"}
applications:
myapp:
type: 'php:8.4'
runtime:
extensions:
- raphf
- http
- igbinary
- redis
disabled_extensions:
- sqlite3
```
You can also [include configuration options](/create-apps/app-reference/single-runtime-image.md#extensions) for specific extensions.
The following table shows all extensions that are available (Avail) and on by default (Def).
You can turn on the available ones with the `extensions` key
and turn off those on by default with the `disabled_extensions` key.
(Extensions marked with `*` are built in and can't be turned off.)
Extension
5.4
5.5
5.6
7.0
7.1
7.2
7.3
7.4
8.0
8.1
8.2
8.3
8.4
amqp
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
apc
Avail
apcu
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
apcu_bc
Avail
Avail
Avail
Avail
Avail
applepay
Avail
Avail
Avail
Avail
bcmath
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
blackfire
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
bz2
Avail
Def
Def
Def
Def
Def
Def
Def
Def
Def
calendar
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
ctype
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
curl
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
datadog
Avail
Avail
dba
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
dom
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
enchant
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
event
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
exif
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
ffi
Avail
Avail
Avail
Avail
Avail
fileinfo
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
ftp
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
gd
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
gearman
Avail
Avail
Avail
geoip
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
gettext
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
gmp
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
gnupg
Avail
Avail
http
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
iconv
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
igbinary
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
imagick
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail with webp
Avail with webp
Avail with webp
Avail with webp
imap
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
interbase
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
intl
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
ioncube
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
json
Def
Def
Def
Def
Def
Def
*
*
*
*
*
ldap
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
mailparse
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
mbstring
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
mcrypt
Def
Def
Def
Avail
Avail
memcache
Avail
Avail
Avail
memcached
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
mongo
Avail
Avail
Avail
mongodb
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
msgpack
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
mssql
Avail
Avail
Avail
mysql
Def
Def
Def
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
mysqli
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
mysqlnd
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
newrelic
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
oauth
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
odbc
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
opcache
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
openswoole
Avail
Avail
opentelemetry
Avail
Avail
pdo
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
pdo_dblib
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
pdo_firebird
Avail
Avail
Avail
Avail
Avail
pdo_mysql
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
pdo_odbc
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
pdo_pgsql
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
pdo_sqlite
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
pdo_sqlsrv
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
pecl-http
Avail
pgsql
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
phar
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
phpdbg
Avail
pinba
Avail
Avail
Avail
posix
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
propro
Avail
protobuf
Avail
pspell
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
pthreads
Avail
Avail
raphf
Avail
Avail
Avail
Avail
Avail
Avail
Avail
rdkafka
Avail
Avail
Avail
readline
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
recode
Avail
Avail
Avail
Avail
Avail
Avail
Avail
redis
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
shmop
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
simplexml
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
snmp
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
soap
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
sockets
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
sodium
Avail
Avail
Avail
Avail
Avail
Avail
Avail
sourceguardian
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
spplus
Avail
Avail
sqlite3
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
sqlsrv
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
ssh2
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
swoole
Avail
Avail
sybase
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
sysvmsg
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
sysvsem
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
sysvshm
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
tideways
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
tideways_xhprof
Avail
Avail
Avail
Avail
Avail
Avail
Avail
tidy
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
tokenizer
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
uuid
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
wddx
Avail
Avail
Avail
Avail
Avail
xcache
Avail
Avail
xdebug
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
xhprof
Avail
Avail
Avail
xml
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
xmlreader
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
xmlrpc
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
xmlwriter
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
xsl
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
yaml
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
zbarcode
Avail
Avail
Avail
Avail
zendopcache
Def
*
*
*
*
*
*
*
*
*
*
*
*
zip
Def
Def
Def
Def
Def
Def
Def
Def
Def
Def
Some built-in modules are always on:
- `date`
- `filter`
- `hash`
- `json` (from 8.0)
- `libxml`
- `openssl`
- `pcntl`
- `pcre`
- `Reflection`
- `session`
- `SPL`
- `standard`
- `Zend OPcache` (from 5.5)
- `zlib`
To see a complete list of the compiled PHP extensions, run the following [CLI command](../../administration/cli/_index.md):
```bash
upsun ssh "php -m"
```
## Custom PHP extensions
It's possible to use an extension not listed here,
but it takes slightly more work:
1. Download the `.so` file for the extension as part of your build hook using `curl` or similar.
It can also be added to your Git repository if the file isn't publicly downloadable,
but committing large binary blobs to Git is generally not recommended.
2. Load the extension using an absolute path by [customizing the PHP settings](./_index.md#customize-php-settings)
For example, if the extension is named `spiffy.so` and is in your [app root](/create-apps/app-reference/single-runtime-image.md#root-directory),
your configuration looks like the following:
```yaml {configFile="app"}
applications:
myapp:
type: 'php:8.4'
variables:
php:
extension: /app/spiffy.so
```
# Best practices [HTTP caching](https://docs.upsun.com/learn/bestpractices/http-caching.html)
You can configure HTTP caching for your site on Upsun in several ways.
Which one you should use depends on your specific use case.
You should use only one of these at a time and disable any others.
Mixing them together most likely results in stale cache that can't be cleared.
## The Upsun router cache
Every project includes a router instance that includes [optional HTTP caching](/define-routes/cache.md).
It's reasonably configurable and obeys HTTP cache directives, but doesn't support push-based clearing.
If you're uncertain what caching tool to use, start with this one.
It's enough for most uses.
## A Content Delivery Network (CDN)
Upsun is compatible with most commercial CDNs.
CDNs generally offer the best performance as they're the only option that includes multiple geographic locations.
But they do tend to be the most expensive option.
See more on setting up [Fastly](/domains/cdn/fastly.md) and [Cloudflare](/domains/cdn/cloudflare.md).
The methods for other CDNs are similar.
## Varnish
Upsun offers a [Varnish service](/add-services/varnish.md) that you can insert between the router and your app.
It has roughly the same performance as the router cache.
Varnish is more configurable, but it requires you to be comfortable with Varnish Configuration Language (VCL).
Upsun doesn't help with VCL configuration and a misconfiguration may be difficult to debug.
Varnish supports [clearing cache with a push](/add-services/varnish.md#clear-cache-with-a-push),
but access control is complicated by the inability to have [circular relationships](/add-services/varnish.md#circular-relationships).
Generally speaking, you should use Varnish only if your application requires push-based clearing or relies on Varnish-specific business logic.
## App-specific caching
Many web apps and frameworks include a built-in web cache layer that mimics what Varnish or the Router cache would do.
Most of the time they're slower than a dedicated caching service as they still require invoking the app server
and only serve as a fallback for users that don't have a dedicated caching service available.
Generally speaking, use app-specific web cache only when it includes app-specific business logic you depend on,
such as app-sensitive selective cache clearing or partial page caching.
Note that this refers only to HTTP caching.
Many apps have an internal app cache for data objects and similar information.
That should remain active regardless of the HTTP cache in use.
## Cookies and caching
HTTP-based caching systems generally default to including cookie values in cache keys
to avoid serving authenticated content to the wrong user.
While this is a safe default, it means that *any* cookie effectively disables the cache,
including mundane cookies like analytics.
The solution is to set which cookies should impact the cache and limit them to session cookies.
For the router cache, see [cookies in HTTP caching](/define-routes/cache.md#cookies).
For other cache systems, consult their documentation.
# JavaScript/Node.js [Manage Node.js versions](https://docs.upsun.com/languages/nodejs/node-version.html)
Note
You can now use composable image (BETA) to install runtimes and tools in your application container. To find out more, see the dedicated documentation page.
Each Upsun container image includes a specific language in a specific version.
A set of dependencies is also provided based on that language version.
This ensures that your application container is as small and efficient as possible.
Therefore, by default, when you use a Upsun container image,
you use the Node.js version that's included in that image, if any.
If you want to use a different Node.js version, use a version manager to install it yourself.
You can use one of the following version managers:
- [Use `n`](#use-n)
- [Use `nvm`](#use-nvm)
Both of the recommendations use a `.nvmrc` file to specify the desired Node.js version.
You could also specify a different file or use [environment variables](../../development/variables/_index.md).
## Use `n`
The [`n` package](https://github.com/tj/n) works for various Unix-like systems,
including Windows Subsystem for Linux.
1. Add the desired Node.js version to your environment using `.nvmrc`, `.n-node-version`, `.node-version`, or `package.json`.
Create a .n-node-version or .node-version file in your app root:
.n-node-version or .node-version
16.13.2
Add an engines.node property to your package.json.
This property accepts either an exact version or a range:
package.json
{"engines":{"node":">=0.10.3 <15"}}
2. Add it as a dependency:
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
myapp:
type: 'python:3.9'
dependencies:
nodejs:
n: "*"
```
Adding it as a dependency ensures it's cached for future builds.
3. Set the location of the `n` files using the `N_PREFIX` environment variable:
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
myapp:
type: 'python:3.9'
dependencies:
nodejs:
n: "*"
variables:
env:
N_PREFIX: /app/.global
```
4. Install the specified version of Node.js in a [`build` hook](../../create-apps/hooks/hooks-comparison.md#build-hook):
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
myapp:
type: 'python:3.9'
dependencies:
nodejs:
n: "*"
variables:
env:
N_PREFIX: /app/.global
hooks:
build: |
# Exit the hook on any failure
set -e
# Install the version specified in the .nvmrc file
n auto
# Reset the location hash to recognize the newly installed version
hash -r
```
Now your hooks should be able to use the specified version of Node.js.
You can verify this by running `node -v`.
Your final app configuration should look something like this:
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
myapp:
type: 'python:3.9'
dependencies:
nodejs:
n: "*"
variables:
env:
N_PREFIX: /app/.global
hooks:
build: |
# Exit the hook on any failure
set -e
# Install the version specified in the .nvmrc file
n auto
# Reset the location hash to recognize the newly installed version
hash -r
```
## Use `nvm`
[Node Version Manager (`nvm`)](https://github.com/nvm-sh/nvm) is a bash script for managing Node.js versions.
You can use it to:
- Make a specific version available in the build and optionally the runtime container.
- Control the specific versions to be installed with [environment variables](../../development/variables/_index.md),
meaning you can also have different versions in different environments.
To use `nvm`, follow these steps:
1. Define which `nvm` version to use using an [environment variable](../../development/variables/_index.md).
Add it to your [app configuration](../../create-apps/_index.md):
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
myapp:
type: 'python:3.9'
variables:
env:
# Update for your desired NVM version.
NVM_VERSION: v0.39.3
```
2. Define your desired Node.js version using an environment variable.
For your base version, set it in your app configuration:
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
myapp:
type: 'python:3.9'
variables:
env:
# Update these for your desired NVM and Node versions.
NVM_VERSION: v0.39.3
NODE_VERSION: v18.14.2
```
To get different versions in different environments, [set environment-specific variables](../../development/variables/set-variables.md#create-environment-specific-variables).
3. Add a `.nvm` directory to your cache in your [build hook](../../create-apps/hooks/_index.md):
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
myapp:
type: 'python:3.9'
variables:
env:
# Update these for your desired NVM and Node versions.
NVM_VERSION: v0.39.3
NODE_VERSION: v18.14.2
hooks:
build: |
set -e
unset NPM_CONFIG_PREFIX
export NVM_DIR="$PLATFORM_APP_DIR/.nvm"
# Link cache with app
if [ ! -d "$PLATFORM_CACHE_DIR/.nvm" ]; then
mkdir -p $PLATFORM_CACHE_DIR/.nvm
fi
ln -s $PLATFORM_CACHE_DIR/.nvm $NVM_DIR
```
Note
Instead of using a symlink between your cache and application directories,
you might need to copy the content of $PLATFORM_CACHE_DIR/.nvm into $PLATFORM_APP_DIR/.nvm manually.
To do so, run the following command:
4. Use the cache directory and install based on the variables if not present:
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
myapp:
type: 'python:3.9'
variables:
env:
# Update these for your desired NVM and Node versions.
NVM_VERSION: v0.39.3
NODE_VERSION: v18.14.2
hooks:
build: |
...
# Check for Node.js version and install if not present
if [ ! -d "$PLATFORM_CACHE_DIR/.nvm/versions/node/$NODE_VERSION" ]; then
# Get nvm install script if correct version not present
export NVM_INSTALL_FILE="${PLATFORM_CACHE_DIR}/nvm_${NVM_VERSION}_install.sh"
if [ ! -f "$NVM_INSTALL_FILE" ]; then
wget -nc -O "$NVM_INSTALL_FILE" "https://raw.githubusercontent.com/nvm-sh/nvm/$NVM_VERSION/install.sh"
fi
# Install, automatically using NODE_VERSION
bash $NVM_INSTALL_FILE
fi
# Activate nvm
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
# Use the specified version
nvm use "$NODE_VERSION"
```
5. Optional: To use the specified Node.js version in the runtime container and not just the build,
activate `nvm` via [script](../../development/variables/set-variables.md#set-variables-via-script):
```bash {location=".environment"}
unset NPM_CONFIG_PREFIX
export NVM_DIR="$PLATFORM_APP_DIR/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
```
Your final app configuration should look something like the following:
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
myapp:
type: 'python:3.9'
variables:
env:
# Update these for your desired NVM and Node versions.
NVM_VERSION: v0.39.3
NODE_VERSION: v18.14.2
hooks:
build: |
set -e
unset NPM_CONFIG_PREFIX
export NVM_DIR="$PLATFORM_APP_DIR/.nvm"
# Link cache with app
if [ ! -d "$PLATFORM_CACHE_DIR/.nvm" ]; then
mkdir -p $PLATFORM_CACHE_DIR/.nvm
fi
ln -s $PLATFORM_CACHE_DIR/.nvm $NVM_DIR
# Check for Node.js version and install if not present
if [ ! -d "$PLATFORM_CACHE_DIR/.nvm/versions/node/$NODE_VERSION" ]; then
# Get nvm install script if correct version not present
export NVM_INSTALL_FILE="${PLATFORM_CACHE_DIR}/nvm_${NVM_VERSION}_install.sh"
if [ ! -f "$NVM_INSTALL_FILE" ]; then
wget -nc -O "$NVM_INSTALL_FILE" "https://raw.githubusercontent.com/nvm-sh/nvm/$NVM_VERSION/install.sh"
fi
# Install, automatically using NODE_VERSION
bash $NVM_INSTALL_FILE
fi
# Activate nvm
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
# Use the specified version
nvm use "$NODE_VERSION"
```
# What is Upsun? [Philosophy](https://docs.upsun.com/learn/overview/philosophy.html)
Upsun aims at reducing configuration and making developers more productive.
It abstracts your project infrastructure and manages it for you,
so you never have to configure services like a web server, a MySQL database, or a Redis cache from scratch again.
Upsun is built on one main idea — your server infrastructure is part of your app,
so it should be version controlled along with your app.
Every branch you push to your Git repository can come with bug fixes,
new features, **and** infrastructure changes.
You can then test everything as an independent deployment,
including your application code and all of your services with a copy of their data
(database entries, search index, user files, etc.).
This allows you to preview exactly what your site would look like if you merged your changes to production.
## The basics
On Upsun, a **project** is linked to a Git repository and is composed of one or more **apps**.
An app is a directory in your Git repository with a specific Upsun configuration
and dedicated HTTP endpoints (via the `.upsun/config.yaml` file).
Projects are deployed in **environments**.
An environment is a standalone copy of your live app which can be used for testing,
Q&A, implementing new features, fixing bugs, and so on.
Every project you deploy on Upsun is built as a *virtual cluster* containing a series of containers.
The main branch of your Git repository is always deployed as a production cluster.
Any other branch can be deployed as a staging or development cluster.
There are three types of containers within your cluster,
all usually configured from a single `.upsun/config.yaml` file stored alongside your code:
- The [*router*](/define-routes/_index.md) is a single Nginx process responsible for mapping incoming requests to an app container,
and for optionally providing HTTP caching.
- One or more [*apps*](/create-apps/_index.md) holding the code of your project.
- Some optional [*services*](/add-services/_index.md) like MySQL/MariaDB, Elasticsearch, Redis, or RabbitMQ.
They come as optimized pre-built images.
## The workflow
Every time you deploy a branch to Upsun, the code is *built* and then *deployed* on a new cluster.
The [**build** process](/learn/overview/build-deploy.md#build-steps) looks through the configuration files in your repository
and assembles the necessary containers.
The [**deploy** process](/learn/overview/build-deploy.md#deploy-steps) makes those containers live, replacing the previous
versions, with no service downtime.
Depending on your needs, you can also [set up a **post-deploy** hook](#add-a-post-deploy-hook) to run after your app is deployed and your application container starts accepting traffic.
Adding a [`post-deploy` hook](/create-apps/hooks/hooks-comparison.md#post-deploy-hook) can be useful to run updates that don't require exclusive database access.
Note that if you're using Gatsby to pull from a backend container on the same environment,
you need a `post-deploy` hook to successfully build and deploy your app.
### How your app is built
During the [build step](/learn/overview/build-deploy.md#build-steps),
dependencies specified in `.upsun/config.yaml` are installed on application containers.
You can also customize the build step by providing a [`build` hook](/create-apps/hooks/hooks-comparison.md#build-hook) composed of one or more shell commands
that help create your production codebase.
That could be compiling TypeScript files, running some scripts,
rearranging files on disk, or whatever else you want.
Note that at this point all you have access to is the filesystem;
there are **no services or other databases available**.
Your live website is unaffected.
Once the build step is completed, the filesystem is frozen and a read-only container image is created.
That filesystem is the final build artifact.
### How your app is deployed
Before starting the [deployment](./build-deploy.md#deploy-steps) of your app,
Upsun pauses all incoming requests and holds them to avoid downtime.
Then, the current containers are stopped and the new ones are started.
Upsun then opens networking connections between the various containers,
as specified in `.upsun/config.yaml`.
The connection information for each service is available from the [service environment variables](/development/variables/_index.md#service-environment-variables), or the [`PLATFORM_RELATIONSHIPS` environment variable](/development/variables/use-variables.md).
Similar to the build step, you can define a [deploy hook](/create-apps/hooks/hooks-comparison.md#deploy-hook) to prepare your app.
Your app has complete access to all services, but the filesystem where your code lives is now read-only.
Finally, Upsun opens the floodgates and lets incoming requests through your newly deployed app.
### Add a post-deploy hook
You can add a [`post-deploy` hook](/create-apps/hooks/hooks-comparison.md#post-deploy-hook) to be run after the build and deploy steps.
Similar to the [`deploy` hook](/create-apps/hooks/hooks-comparison.md#deploy-hook),
the `post-deploy` hook only runs once your application container accepts requests.
So you can use it to run updates such as content imports or cache warmups that can be executed simultaneously with normal traffic.
During a redeploy, the `post-deploy` hook is the only hook that is run.
## Get support
If you're facing an issue with Upsun,
open a [support ticket](/learn/overview/get-support).
## What's next?
To get a feeling of what working with Upsun entails,
see the [Get Started](/get-started/_index.md) framework guides.
# Administration [Pricing](https://docs.upsun.com/administration/pricing.html)
Upsun offers flexible, usage-based [pricing](https://upsun.com/pricing/) for organizations and projects.
Note
This page is meant to provide some context for how the pricing model relates to technical work on Upsun.
It is not meant to be your primary resource for the exact costs of certain features.
The official Upsun Pricing page should always be considered the primary source of pricing details.
In general, there are four main dimensions that determine the cost of work on Upsun.
| Pricing dimension | Details |
|---|---|
| Project fees | An individual project on Upsun comes with a consistent monthly cost. The cost includes all of the orchestration and provisioning characteristics that define the Upsun PaaS.
It comes with some baseline features and feature limits, such as infrastructure metrics and a certain number of build minutes. Individual preview environments do not come with their own associated creation cost - you are charged only for the resources those preview environments use during their lifespan (see next row). |
| [Project resources](/manage-resources.md) | Deploying on Upsun allows you fine-grained control over the amount of resources allocated for your application and service containers. CPU, memory, and disk (including backup disk) are calculated across each organization, project, and environment to determine your overall usage for a billing period. |
| [User licenses](/administration/users.md) | Each organization user comes with a license fee. Users can be given different levels of access to singular projects within an organization, or to multiple projects, without changing that license fee. There are two exceptions which are not charged the license fee: Viewers and Viewers who Manage Billing. There are no limits to the number of users you can have in an organization.|
| Feature add-ons | There are additional features that can be added to the organization that come with their own cost. Few of these are available immediately during the Beta phase, but more will be added. |
A given organization's monthly billing is then made up of the sum of each of these dimensions.
You can monitor your spend from the Console via a [current month estimate](/administration/billing/monitor-billing.html#current-month-estimate) and a [next month estimate](/administration/billing/monitor-billing.html#next-month-estimate).
You can also [set billing alerts](/administration/billing/monitor-billing.html#manage-billing-alerts) to receive an email when your current month estimate reaches a defined threshold.
## Dunning process
In instances where a payment has failed, your organization will be immediately restricted. Upsun will proceed to make three separate attempts to take the outstanding balance from your account. These attempts will be made on the 4th, 6th and 11th of the month. If your payment fails after the third attempt on the 11th, your organization will be suspended the following day.
If you are a new Upsun customer and your first payment has failed, your projects will be deleted on the 13th - two days after the final payment attempt.
For all other customers, projects will be deleted 30 days after your organization is suspended on the 11th. You will be notified 10 days before this deletion occurs and a payment will be attempted for the last time. If unsuccessful, all projects on the billing subscription will be deleted.
Be sure to visit the [Pricing page](https://upsun.com/pricing/) for exact details related to Upsun pricing.
# Define routes [Server Side Includes (SSI)](https://docs.upsun.com/define-routes/ssi.html)
SSI commands enable you to include files within other pages.
At its most basic, you can include files within other ones so as not to repeat yourself.
Start by enabling SSI:
```yaml {configFile="routes"}
routes:
"https://{default}/":
type: upstream
upstream: "myapp:http"
ssi:
enabled: true
```
Then create a file you want to include elsewhere:
```html {location="includes/example.html"}
This content can be reused
```
And include it in another file:
```html {location="index.html"}
This content is unique to this page.
```
And your final rendered page includes the other file:
```html {location="index.html"}
This content is unique to this page.
This content can be reused
```
## Caching and dynamic content
You can use SSI to have [caching](./cache.md) and dynamic content in one.
So one file is cached, while another updates dynamically.
For example, you can activate SSI on one route with cache disabled and enable cache on another route:
```yaml {configFile="routes"}
routes:
"https://{default}/":
type: upstream
upstream: "myapp:http"
ssi:
enabled: true
cache:
enabled: false
"https://{default}/cache":
type: upstream
upstream: "myapp:http"
cache:
enabled: true
```
Then create a page that displays the current date and time and is cached for 60 seconds
(the example uses PHP, but any server-side language would work):
```php {location="cache/example.php"}
```
Then you can visit `index.php` and refresh the page a few times.
You see the first number updating to the current time, while the second (included) one only changes every 60 seconds.
For more on SSI, see the [nginx documentation](https://nginx.org/en/docs/http/ngx_http_ssi_module.html).
# Content delivery networks (CDNs) [Set up your Fastly CDN](https://docs.upsun.com/domains/cdn/fastly.html)
You can [use a CDN](./_index.md) to deliver your site's content to users more quickly.
To set up a Fastly CDN with your own Fastly subscription,
follow the instructions on this page.
## Before you begin
You need:
- An up-and-running Upsun project
- A [Fastly](https://www.fastly.com/) CDN subscription
## 1. Avoid double-caching
To avoid stale content that can't be cleared,
avoid using Fastly with [HTTP caching](/define-routes/cache.md).
For routes where Fastly is used,
disable HTTP caching using the following configuration:
```yaml {configFile="routes"}
https://{default}/:
type: upstream
...
cache:
enabled: false
```
## 2. Set up your Fastly CDN
To properly configure your Fastly CDN,
see the Fastly official documentation on [how to get started](https://docs.fastly.com/en/guides/getting-started#_basics).
Then set up a [custom domain](../steps/_index.md).
To get the [DNS challenge to succeed](../troubleshoot.md#ownership-verification),
have your CDN point to your [project's target URL](../../domains/steps/_index.md#1-get-the-target-for-your-project).
## 3. Handle apex domains
To start routing client traffic through Fastly,
[create `CNAME` records for your domain names](../../domains/steps/dns.md)
through your DNS provider.
`CNAME` records can't point to apex domains.
As a workaround, Fastly offers [Anycast options](https://docs.fastly.com/en/guides/using-fastly-with-apex-domains).
## 4. Optional: Protect your site from on-path attacks
An on-path attack occurs when a hacker intercepts
or modifies the communication between a client and a server.
This can lead to sensitive data leaks.
To prevent such attacks, make sure all communication with your site is encrypted through HTTPS
and can't be downgraded to HTTP.
To do so, enable HTTP strict transport security (HSTS).
HSTS forces clients to always communicate with your site over HTTPS.
You can [enable HSTS](https://docs.fastly.com/en/guides/enabling-hsts-through-fastly#forcing-tls-and-enabling-hsts)
in your Fastly account.
All HTTP requests are then automatically redirected to HTTPS.# Set up your local development environment [Use DDEV for local development](https://docs.upsun.com/development/local/ddev.html)
[DDEV](https://ddev.readthedocs.io/en/stable/) is an open-source tool for local development environments.
It allows you to use Docker in your workflows while maintaining a GitOps workflow.
You get fully containerized environments to run everything locally
without having to install tools (including the Upsun CLI, PHP, and Composer) on your machine.
This guide assumes you have a project already running with Upsun and you have the code on your computer.
If you're starting from scratch, first [create a project](/get-started/).
## Before you begin
Make sure your computer meets the [system requirements for DDEV](https://ddev.readthedocs.io/en/stable/#system-requirements).
For the integration to run smoothly, you also need the following tools:
- `jq`
- `base64`
- `perl`
If you don't have these already installed, use your normal package manager.
## 1. Install DDEV
To install DDEV, follow the [DDEV documentation for your operating system](https://ddev.readthedocs.io/en/stable/users/install/ddev-installation/).
This installs the self-contained `ddev` command-line interface (CLI).
For more information on `ddev`, run `ddev help`.
## 2. Add DDEV configuration to your project
Get basic configuration set up for your project by running the following command:
```bash
ddev config
```
Follow the prompts to add the correct DDEV configuration files to your repository.
## 3. Add an API token
To connect DDEV with your Upsun account, use a Upsun API token.
First [create an API token](/administration/cli/api-tokens.md#2-create-an-api-token) in the Console.
Then add the token to your DDEV configuration.
You can do so globally (easiest for most people):
```bash
ddev config global --web-environment-add=UPSUN
_CLI_TOKEN=API_TOKEN
```
You can also add the token only to the project:
```bash
ddev config --web-environment-add=UPSUN
_CLI_TOKEN=API_TOKEN
```
## 4. Optional: Get your project data
To get your environment data (files, database), run the following command:
```bash
ddev pull upsun
```
To skip pulling files, add `--skip-files` to the command.
To skip pulling a database, add `--skip-db` to the command.
## 5. Run your project
Now your project is ready to run:
```bash
ddev start
```
This runs all your hooks and builds your project like on Upsun.
The command returns the project URL `http://PROJECT_NAME.ddev.site/`
as well as a specific port on `http://127.0.0.1`.
To see your project running, open one of these URLs.
## What's next
You've got a project running on a local web server.
Now you can add customizations.
For more ideas and options, see the [DDEV documentation](https://ddev.readthedocs.io/en/stable/).
### Add environment variables
If your project requires environment variables for its hooks or runtime,
add them to the project's DDEV environment:
```yaml {location=".ddev/config.yaml"}
web_environment:
- VARIABLE_NAME: VALUE
```
To apply your changes, run the following command:
```bash
ddev restart
```
# Command line interface (CLI) [CLI Command reference](https://docs.upsun.com/administration/cli/reference.html)
# Upsun CLI 5.0.15
- [Installation](/administration/cli#1-install)
- [Open an issue](https://github.com/platformsh/cli/issues)
## All commands
* [`clear-cache`](#clear-cache)
* [`decode`](#decode)
* [`docs`](#docs)
* [`help`](#help)
* [`list`](#list)
* [`multi`](#multi)
* [`web`](#web)
**activity**
* [`activity:cancel`](#activitycancel)
* [`activity:get`](#activityget)
* [`activity:list`](#activitylist)
* [`activity:log`](#activitylog)
**app**
* [`app:config-get`](#appconfig-get)
* [`app:config-validate`](#appconfig-validate)
* [`app:list`](#applist)
**auth**
* [`auth:api-token-login`](#authapi-token-login)
* [`auth:browser-login`](#authbrowser-login)
* [`auth:info`](#authinfo)
* [`auth:logout`](#authlogout)
* [`auth:verify-phone-number`](#authverify-phone-number)
**backup**
* [`backup:create`](#backupcreate)
* [`backup:delete`](#backupdelete)
* [`backup:get`](#backupget)
* [`backup:list`](#backuplist)
* [`backup:restore`](#backuprestore)
**certificate**
* [`certificate:add`](#certificateadd)
* [`certificate:delete`](#certificatedelete)
* [`certificate:get`](#certificateget)
* [`certificate:list`](#certificatelist)
**commit**
* [`commit:get`](#commitget)
* [`commit:list`](#commitlist)
**db**
* [`db:dump`](#dbdump)
* [`db:sql`](#dbsql)
**domain**
* [`domain:add`](#domainadd)
* [`domain:delete`](#domaindelete)
* [`domain:get`](#domainget)
* [`domain:list`](#domainlist)
* [`domain:update`](#domainupdate)
**environment**
* [`environment:activate`](#environmentactivate)
* [`environment:branch`](#environmentbranch)
* [`environment:checkout`](#environmentcheckout)
* [`environment:delete`](#environmentdelete)
* [`environment:drush`](#environmentdrush)
* [`environment:http-access`](#environmenthttp-access)
* [`environment:info`](#environmentinfo)
* [`environment:init`](#environmentinit)
* [`environment:list`](#environmentlist)
* [`environment:logs`](#environmentlogs)
* [`environment:merge`](#environmentmerge)
* [`environment:pause`](#environmentpause)
* [`environment:push`](#environmentpush)
* [`environment:redeploy`](#environmentredeploy)
* [`environment:relationships`](#environmentrelationships)
* [`environment:resume`](#environmentresume)
* [`environment:scp`](#environmentscp)
* [`environment:ssh`](#environmentssh)
* [`environment:synchronize`](#environmentsynchronize)
* [`environment:url`](#environmenturl)
* [`environment:xdebug`](#environmentxdebug)
**integration**
* [`integration:activity:get`](#integrationactivityget)
* [`integration:activity:list`](#integrationactivitylist)
* [`integration:activity:log`](#integrationactivitylog)
* [`integration:add`](#integrationadd)
* [`integration:delete`](#integrationdelete)
* [`integration:get`](#integrationget)
* [`integration:list`](#integrationlist)
* [`integration:update`](#integrationupdate)
* [`integration:validate`](#integrationvalidate)
**local**
* [`local:dir`](#localdir)
**metrics**
* [`metrics:all`](#metricsall)
* [`metrics:cpu`](#metricscpu)
* [`metrics:disk-usage`](#metricsdisk-usage)
* [`metrics:memory`](#metricsmemory)
**mount**
* [`mount:download`](#mountdownload)
* [`mount:list`](#mountlist)
* [`mount:upload`](#mountupload)
**operation**
* [`operation:list`](#operationlist)
* [`operation:run`](#operationrun)
**organization**
* [`organization:billing:address`](#organizationbillingaddress)
* [`organization:billing:profile`](#organizationbillingprofile)
* [`organization:create`](#organizationcreate)
* [`organization:delete`](#organizationdelete)
* [`organization:info`](#organizationinfo)
* [`organization:list`](#organizationlist)
* [`organization:subscription:list`](#organizationsubscriptionlist)
* [`organization:user:add`](#organizationuseradd)
* [`organization:user:delete`](#organizationuserdelete)
* [`organization:user:get`](#organizationuserget)
* [`organization:user:list`](#organizationuserlist)
* [`organization:user:projects`](#organizationuserprojects)
* [`organization:user:update`](#organizationuserupdate)
**project**
* [`project:clear-build-cache`](#projectclear-build-cache)
* [`project:create`](#projectcreate)
* [`project:delete`](#projectdelete)
* [`project:get`](#projectget)
* [`project:info`](#projectinfo)
* [`project:init`](#projectinit)
* [`project:list`](#projectlist)
* [`project:set-remote`](#projectset-remote)
**repo**
* [`repo:cat`](#repocat)
* [`repo:ls`](#repols)
* [`repo:read`](#reporead)
**resources**
* [`resources:build:get`](#resourcesbuildget)
* [`resources:build:set`](#resourcesbuildset)
* [`resources:get`](#resourcesget)
* [`resources:set`](#resourcesset)
* [`resources:size:list`](#resourcessizelist)
**route**
* [`route:get`](#routeget)
* [`route:list`](#routelist)
**service**
* [`service:list`](#servicelist)
* [`service:mongo:dump`](#servicemongodump)
* [`service:mongo:export`](#servicemongoexport)
* [`service:mongo:restore`](#servicemongorestore)
* [`service:mongo:shell`](#servicemongoshell)
* [`service:redis-cli`](#serviceredis-cli)
**source-operation**
* [`source-operation:list`](#source-operationlist)
* [`source-operation:run`](#source-operationrun)
**ssh-cert**
* [`ssh-cert:load`](#ssh-certload)
**ssh-key**
* [`ssh-key:add`](#ssh-keyadd)
* [`ssh-key:delete`](#ssh-keydelete)
* [`ssh-key:list`](#ssh-keylist)
**subscription**
* [`subscription:info`](#subscriptioninfo)
**team**
* [`team:create`](#teamcreate)
* [`team:delete`](#teamdelete)
* [`team:get`](#teamget)
* [`team:list`](#teamlist)
* [`team:project:add`](#teamprojectadd)
* [`team:project:delete`](#teamprojectdelete)
* [`team:project:list`](#teamprojectlist)
* [`team:update`](#teamupdate)
* [`team:user:add`](#teamuseradd)
* [`team:user:delete`](#teamuserdelete)
* [`team:user:list`](#teamuserlist)
**tunnel**
* [`tunnel:close`](#tunnelclose)
* [`tunnel:info`](#tunnelinfo)
* [`tunnel:list`](#tunnellist)
* [`tunnel:open`](#tunnelopen)
* [`tunnel:single`](#tunnelsingle)
**user**
* [`user:add`](#useradd)
* [`user:delete`](#userdelete)
* [`user:get`](#userget)
* [`user:list`](#userlist)
* [`user:update`](#userupdate)
**variable**
* [`variable:create`](#variablecreate)
* [`variable:delete`](#variabledelete)
* [`variable:get`](#variableget)
* [`variable:list`](#variablelist)
* [`variable:update`](#variableupdate)
**worker**
* [`worker:list`](#workerlist)
## `clear-cache`
Clear the CLI cache
Aliases: `cc`
### Usage
```
upsun cc
```
#### Options
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `decode`
Decode an encoded string such as PLATFORM_VARIABLES
### Usage
```
upsun decode [-P|--property PROPERTY] [--]
```
#### Arguments
* `value`(required)
The variable value to decode
#### Options
* `--property` (`-P`) (expects a value)
The property to view within the variable
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* View "foo" in PLATFORM_VARIABLES:
```
upsun decode "$PLATFORM_VARIABLES" -P foo
```
## `docs`
Open the online documentation
### Usage
```
upsun docs [--browser BROWSER] [--pipe] [--] []...
```
#### Arguments
* `search`(optional; multiple values allowed)
Search term(s)
#### Options
* `--browser` (expects a value)
The browser to use to open the URL. Set 0 for none.
* `--pipe`
Output the URL to stdout.
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Search for information about the CLI:
```
upsun docs CLI
```
## `help`
Displays help for a command
### Usage
```
upsun help [--format FORMAT] [--raw] [--] []
```
The help command displays help for a given command:
upsun help list
You can also output the help in other formats by using the --format option:
upsun help --format=json list
To display the list of available commands, please use the list command.
#### Arguments
* `command_name`(optional)
The command name
#### Options
* `--format` (expects a value)
The output format (txt, json, or md)
* `--raw`
To output raw command help
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `list`
Lists commands
### Usage
```
upsun list [--raw] [--format FORMAT] [--all] [--] []
```
The list command lists all commands:
upsun list
You can also display the commands for a specific namespace:
upsun list project
You can also output the information in other formats by using the --format option:
upsun list --format=xml
It's also possible to get raw list of commands (useful for embedding command runner):
upsun list --raw
#### Arguments
* `command`(required)
The command to execute
* `namespace`(optional)
The namespace name
#### Options
* `--raw`
To output raw command list
* `--format` (expects a value)
The output format (txt, xml, json, or md)
* `--all`
Show all commands, including hidden ones
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `multi`
Execute a command on multiple projects
### Usage
```
upsun multi [-p|--projects PROJECTS] [--continue] [--sort SORT] [--reverse] [--] ()...
```
#### Arguments
* `cmd`(required; multiple values allowed)
The command to execute
#### Options
* `--projects` (`-p`) (expects a value)
A list of project IDs, separated by commas and/or whitespace
* `--continue`
Continue running commands even if an exception is encountered
* `--sort` (expects a value)
A property by which to sort the list of project options
* `--reverse`
Reverse the order of project options
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* List variables on the "main" environment for multiple projects:
```
upsun multi -p l7ywemwizmmgb,o43m25zns6k2d,3nyujoslhydhx -- var -e main
```
## `web`
Open the project in the Web Console
### Usage
```
upsun web [--browser BROWSER] [--pipe] [-p|--project PROJECT] [-e|--environment ENVIRONMENT]
```
#### Options
* `--browser` (expects a value)
The browser to use to open the URL. Set 0 for none.
* `--pipe`
Output the URL to stdout.
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `activity:cancel`
Cancel an activity
### Usage
```
upsun activity:cancel [-t|--type TYPE] [-x|--exclude-type EXCLUDE-TYPE] [-a|--all] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--] []
```
#### Arguments
* `id`(optional)
The activity ID. Defaults to the most recent cancellable activity.
#### Options
* `--type` (`-t`) (expects a value)
Filter by type (when selecting a default activity). Values may be split by commas (e.g. "a,b,c") and/or whitespace. The % or * characters can be used as a wildcard for the type, e.g. '%var%' to select variable-related activities.
* `--exclude-type` (`-x`) (expects a value)
Exclude by type (when selecting a default activity). Values may be split by commas (e.g. "a,b,c") and/or whitespace. The % or * characters can be used as a wildcard to exclude types.
* `--all` (`-a`)
Check recent activities on all environments (when selecting a default activity)
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `activity:get`
View detailed information on a single activity
### Usage
```
upsun activity:get [-P|--property PROPERTY] [-t|--type TYPE] [-x|--exclude-type EXCLUDE-TYPE] [--state STATE] [--result RESULT] [-i|--incomplete] [-a|--all] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [--date-fmt DATE-FMT] [--] []
```
#### Arguments
* `id`(optional)
The activity ID. Defaults to the most recent activity.
#### Options
* `--property` (`-P`) (expects a value)
The property to view
* `--type` (`-t`) (expects a value)
Filter by type (when selecting a default activity). Values may be split by commas (e.g. "a,b,c") and/or whitespace. The % or * characters can be used as a wildcard for the type, e.g. '%var%' to select variable-related activities.
* `--exclude-type` (`-x`) (expects a value)
Exclude by type (when selecting a default activity). Values may be split by commas (e.g. "a,b,c") and/or whitespace. The % or * characters can be used as a wildcard to exclude types.
* `--state` (expects a value)
Filter by state (when selecting a default activity): in_progress, pending, complete, or cancelled. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--result` (expects a value)
Filter by result (when selecting a default activity): success or failure
* `--incomplete` (`-i`)
Include only incomplete activities (when selecting a default activity). This is a shorthand for --state=in_progress,pending
* `--all` (`-a`)
Check recent activities on all environments (when selecting a default activity)
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Find the time a project was created:
```
upsun activity:get --all --type project.create -P completed_at
```
* Find the duration (in seconds) of the last activity:
```
upsun activity:get -P duration
```
## `activity:list`
Get a list of activities for an environment or project
Aliases: `activities`, `act`
### Usage
```
upsun activities [-t|--type TYPE] [-x|--exclude-type EXCLUDE-TYPE] [--limit LIMIT] [--start START] [--state STATE] [--result RESULT] [-i|--incomplete] [-a|--all] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [--date-fmt DATE-FMT] [-p|--project PROJECT] [-e|--environment ENVIRONMENT]
```
#### Options
* `--type` (`-t`) (expects a value)
Filter activities by type For a list of types see: https://docs.upsun.com/integrations/activity/reference.html#type Values may be split by commas (e.g. "a,b,c") and/or whitespace. The first part of the activity name can be omitted, e.g. 'cron' can select 'environment.cron' activities. The % or * characters can be used as a wildcard, e.g. '%var%' to select variable-related activities.
* `--exclude-type` (`-x`) (expects a value)
Exclude activities by type. Values may be split by commas (e.g. "a,b,c") and/or whitespace. The first part of the activity name can be omitted, e.g. 'cron' can exclude 'environment.cron' activities. The % or * characters can be used as a wildcard to exclude types.
* `--limit` (expects a value)
Limit the number of results displayed
* `--start` (expects a value)
Only activities created before this date will be listed
* `--state` (expects a value)
Filter activities by state: in_progress, pending, complete, or cancelled. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--result` (expects a value)
Filter activities by result: success or failure
* `--incomplete` (`-i`)
Only list incomplete activities
* `--all` (`-a`)
List activities on all environments
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: id*, created*, description*, progress*, state*, result*, completed, environments, time_build, time_deploy, time_execute, time_wait, type (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* List recent activities for the current environment:
```
upsun activity:list
```
* List all recent activities for the current project:
```
upsun activity:list --all
```
* List recent pushes:
```
upsun activity:list --type push
```
* List all recent activities excluding crons and redeploys:
```
upsun activity:list --exclude-type '*.cron,*.backup*'
```
* List pushes made before 15 March:
```
upsun activity:list --type push --start 2015-03-15
```
* List up to 25 incomplete activities:
```
upsun activity:list --limit 25 -i
```
## `activity:log`
Display the log for an activity
### Usage
```
upsun activity:log [--refresh REFRESH] [-t|--timestamps] [--type TYPE] [-x|--exclude-type EXCLUDE-TYPE] [--state STATE] [--result RESULT] [-i|--incomplete] [-a|--all] [--date-fmt DATE-FMT] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--] []
```
#### Arguments
* `id`(optional)
The activity ID. Defaults to the most recent activity.
#### Options
* `--refresh` (expects a value)
Activity refresh interval (seconds). Set to 0 to disable refreshing.
* `--timestamps` (`-t`)
Display a timestamp next to each message
* `--type` (expects a value)
Filter by type (when selecting a default activity). Values may be split by commas (e.g. "a,b,c") and/or whitespace. The % or * characters can be used as a wildcard for the type, e.g. '%var%' to select variable-related activities.
* `--exclude-type` (`-x`) (expects a value)
Exclude by type (when selecting a default activity). Values may be split by commas (e.g. "a,b,c") and/or whitespace. The % or * characters can be used as a wildcard to exclude types.
* `--state` (expects a value)
Filter by state (when selecting a default activity): in_progress, pending, complete, or cancelled. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--result` (expects a value)
Filter by result (when selecting a default activity): success or failure
* `--incomplete` (`-i`)
Include only incomplete activities (when selecting a default activity). This is a shorthand for --state=in_progress,pending
* `--all` (`-a`)
Check recent activities on all environments (when selecting a default activity)
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Display the log for the last push on the current environment:
```
upsun activity:log --type environment.push
```
* Display the log for the last activity on the current project:
```
upsun activity:log --all
```
* Display the log for the last push, with microsecond timestamps:
```
upsun activity:log -a -t --type %push --date-fmt 'Y-m-d\TH:i:s.uP'
```
## `app:config-get`
View the configuration of an app
### Usage
```
upsun app:config-get [-P|--property PROPERTY] [--refresh] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP] [-i|--identity-file IDENTITY-FILE]
```
#### Options
* `--property` (`-P`) (expects a value)
The configuration property to view
* `--refresh`
Whether to refresh the cache
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--identity-file` (`-i`) (expects a value)
[Deprecated option, no longer used]
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `app:config-validate`
Validate the config files of a project
Aliases: `validate`
### Usage
```
upsun app:config-validate
```
#### Options
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|vv|vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Validate the project configuration files in your current directory:
```
upsun app:config-validate
```
## `app:list`
List apps in the project
Aliases: `apps`
### Usage
```
upsun apps [--refresh] [--pipe] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--format FORMAT] [-c|--columns COLUMNS] [--no-header]
```
#### Options
* `--refresh`
Whether to refresh the cache
* `--pipe`
Output a list of app names only
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: name*, type*, disk, path, size (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `auth:api-token-login`
Log in to Upsun using an API token
### Usage
```
upsun auth:api-token-login
```
Use this command to log in to your Upsun account using an API token.
You can create an account at:
https://auth.upsun.com/register
Alternatively, to log in to the CLI with a browser, run:
upsun auth:browser-login
#### Options
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `auth:browser-login`
Log in to Upsun via a browser
Aliases: `login`
### Usage
```
upsun login [-f|--force] [--method METHOD] [--max-age MAX-AGE] [--browser BROWSER] [--pipe]
```
Use this command to log in to the Upsun CLI using a web browser.
It launches a temporary local website which redirects you to log in if
necessary, and then captures the resulting authorization code.
Your system's default browser will be used. You can override this using the
--browser option.
Alternatively, to log in using an API token (without a browser), run:
upsun auth:api-token-login
To authenticate non-interactively, configure an API token using the
UPSUN_CLI_TOKEN environment variable.
#### Options
* `--force` (`-f`)
Log in again, even if already logged in
* `--method` (expects a value)
Require specific authentication method(s)
* `--max-age` (expects a value)
The maximum age (in seconds) of the web authentication session
* `--browser` (expects a value)
The browser to use to open the URL. Set 0 for none.
* `--pipe`
Output the URL to stdout.
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `auth:info`
Display your account information
### Usage
```
upsun auth:info [--no-auto-login] [-P|--property PROPERTY] [--refresh] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [--] []
```
#### Arguments
* `property`(optional)
The account property to view
#### Options
* `--no-auto-login`
Skips auto login. Nothing will be output if not logged in, and the exit code will be 0, assuming no other errors.
* `--property` (`-P`) (expects a value)
The account property to view (alternate syntax)
* `--refresh`
Whether to refresh the cache
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Print your user ID:
```
upsun auth:info id
```
* Print your email address:
```
upsun auth:info email
```
* Print your user ID (or nothing if not logged in):
```
upsun auth:info id --no-auto-login
```
## `auth:logout`
Log out of Upsun
Aliases: `logout`
### Usage
```
upsun logout [-a|--all] [--other]
```
#### Options
* `--all` (`-a`)
Log out from all local sessions
* `--other`
Log out from other local sessions
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `auth:verify-phone-number`
Verify your phone number interactively
### Usage
```
upsun auth:verify-phone-number
```
#### Options
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `backup:create`
Make a backup of an environment
Aliases: `backup`
### Usage
```
upsun backup [--live] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-W|--no-wait] [--wait] [--] []
```
#### Arguments
* `environment`(optional)
The environment
#### Options
* `--live`
Live backup: do not stop the environment. If set, this leaves the environment running and open to connections during the backup. This reduces downtime, at the risk of backing up data in an inconsistent state.
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Make a backup of the current environment:
```
upsun backup:create
```
* Request a backup (and exit quickly):
```
upsun backup:create --no-wait
```
* Make a backup avoiding downtime (but risking inconsistency):
```
upsun backup:create --live
```
## `backup:delete`
Delete an environment backup
### Usage
```
upsun backup:delete [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-W|--no-wait] [--wait] [--] []
```
#### Arguments
* `backup`(optional)
The ID of the backup. Required in non-interactive mode.
#### Options
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `backup:get`
View an environment backup
### Usage
```
upsun backup:get [-P|--property PROPERTY] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--date-fmt DATE-FMT] [--] []
```
#### Arguments
* `backup`(optional)
The ID of the backup. Defaults to the most recent one.
#### Options
* `--property` (`-P`) (expects a value)
The backup property to display.
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `backup:list`
List available backups of an environment
Aliases: `backups`
### Usage
```
upsun backups [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [--date-fmt DATE-FMT] [-p|--project PROJECT] [-e|--environment ENVIRONMENT]
```
#### Options
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: created_at*, id*, restorable*, automated, commit_id, expires_at, index, live, status, updated_at (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Display backups including the "live" and "commit_id" columns:
```
upsun backup:list -c+live,commit_id
```
## `backup:restore`
Restore an environment backup
### Usage
```
upsun backup:restore [--target TARGET] [--branch-from BRANCH-FROM] [--no-code] [--resources-init RESOURCES-INIT] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-W|--no-wait] [--wait] [--] []
```
#### Arguments
* `backup`(optional)
The ID of the backup. Defaults to the most recent one
#### Options
* `--target` (expects a value)
The environment to restore to. Defaults to the backup's current environment
* `--branch-from` (expects a value)
If the --target does not yet exist, this specifies the parent of the new environment
* `--no-code`
Do not restore code, only data.
* `--resources-init` (expects a value)
Set the resources to use for new services: parent, default or minimum. If not set, "parent" will be used.
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Restore the most recent backup:
```
upsun backup:restore
```
* Restore a specific backup:
```
upsun backup:restore 92c9a4b2aa75422efb3d
```
## `certificate:add`
Add an SSL certificate to the project
### Usage
```
upsun certificate:add [--cert CERT] [--key KEY] [--chain CHAIN] [-p|--project PROJECT] [-W|--no-wait] [--wait]
```
#### Options
* `--cert` (expects a value)
The path to the certificate file
* `--key` (expects a value)
The path to the certificate private key file
* `--chain` (expects a value)
The path to the certificate chain file
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `certificate:delete`
Delete a certificate from the project
### Usage
```
upsun certificate:delete [-p|--project PROJECT] [-W|--no-wait] [--wait] [--]
```
#### Arguments
* `id`(required)
The certificate ID (or the start of it)
#### Options
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `certificate:get`
View a certificate
### Usage
```
upsun certificate:get [-P|--property PROPERTY] [--date-fmt DATE-FMT] [-p|--project PROJECT] [--]
```
#### Arguments
* `id`(required)
The certificate ID (or the start of it)
#### Options
* `--property` (`-P`) (expects a value)
The certificate property to view
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `certificate:list`
List project certificates
Aliases: `certificates`, `certs`
### Usage
```
upsun certificates [--domain DOMAIN] [--exclude-domain EXCLUDE-DOMAIN] [--issuer ISSUER] [--only-auto] [--no-auto] [--ignore-expiry] [--only-expired] [--no-expired] [--pipe-domains] [--date-fmt DATE-FMT] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [-p|--project PROJECT]
```
#### Options
* `--domain` (expects a value)
Filter by domain name (case-insensitive search)
* `--exclude-domain` (expects a value)
Exclude certificates, matching by domain name (case-insensitive search)
* `--issuer` (expects a value)
Filter by issuer
* `--only-auto`
Show only auto-provisioned certificates
* `--no-auto`
Show only manually added certificates
* `--ignore-expiry`
Show both expired and non-expired certificates
* `--only-expired`
Show only expired certificates
* `--no-expired`
Show only non-expired certificates (default)
* `--pipe-domains`
Only return a list of domain names covered by the certificates
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: created, domains, expires, id, issuer. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Output a list of domains covered by valid certificates:
```
upsun certificate:list --pipe-domains --no-expired
```
## `commit:get`
Show commit details
### Usage
```
upsun commit:get [-P|--property PROPERTY] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--date-fmt DATE-FMT] [--] []
```
#### Arguments
* `commit`(optional)
The commit SHA. This can also accept "HEAD", and caret (^) or tilde (~) suffixes for parent commits.
#### Options
* `--property` (`-P`) (expects a value)
The commit property to display.
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Display the current commit on the environment:
```
upsun commit:get
```
* Display the previous commit:
```
upsun commit:get HEAD~
```
* Display the 3rd commit before the current one:
```
upsun commit:get HEAD~3
```
* Display the email address of the last commit author:
```
upsun commit:get -P author.email
```
## `commit:list`
List commits
Aliases: `commits`
### Usage
```
upsun commits [--limit LIMIT] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [--date-fmt DATE-FMT] [--] []
```
#### Arguments
* `commit`(optional)
The starting Git commit SHA. This can also accept "HEAD", and caret (^) or tilde (~) suffixes for parent commits.
#### Options
* `--limit` (expects a value)
The number of commits to display.
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: author, date, sha, summary. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Display commits on an environment:
```
upsun commit:list
```
* Display commits starting from two before the current one:
```
upsun commit:list HEAD~2
```
## `db:dump`
Create a local dump of the remote database
### Usage
```
upsun db:dump [--schema SCHEMA] [-f|--file FILE] [-d|--directory DIRECTORY] [-z|--gzip] [-t|--timestamp] [-o|--stdout] [--table TABLE] [--exclude-table EXCLUDE-TABLE] [--schema-only] [--charset CHARSET] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP] [-r|--relationship RELATIONSHIP]
```
#### Options
* `--schema` (expects a value)
The schema to dump. Omit to use the default schema (usually "main").
* `--file` (`-f`) (expects a value)
A custom filename for the dump
* `--directory` (`-d`) (expects a value)
A custom directory for the dump
* `--gzip` (`-z`)
Compress the dump using gzip
* `--timestamp` (`-t`)
Add a timestamp to the dump filename
* `--stdout` (`-o`)
Output to STDOUT instead of a file
* `--table` (expects a value)
Table(s) to include
* `--exclude-table` (expects a value)
Table(s) to exclude
* `--schema-only`
Dump only schemas, no data
* `--charset` (expects a value)
The character set encoding for the dump
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--relationship` (`-r`) (expects a value)
The service relationship to use
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Create an SQL dump file:
```
upsun db:dump
```
* Create a gzipped SQL dump file named "dump.sql.gz":
```
upsun db:dump --gzip -f dump.sql.gz
```
## `db:sql`
Run SQL on the remote database
Aliases: `sql`
### Usage
```
upsun sql [--raw] [--schema SCHEMA] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP] [-r|--relationship RELATIONSHIP] [--] []
```
#### Arguments
* `query`(optional)
An SQL statement to execute
#### Options
* `--raw`
Produce raw, non-tabular output
* `--schema` (expects a value)
The schema to use. Omit to use the default schema (usually "main"). Pass an empty string to not use any schema.
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--relationship` (`-r`) (expects a value)
The service relationship to use
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Open an SQL console on the remote database:
```
upsun db:sql
```
* View tables on the remote database:
```
upsun db:sql 'SHOW TABLES'
```
* Import a dump file into the remote database:
```
upsun db:sql < dump.sql
```
## `domain:add`
Add a new domain to the project
### Usage
```
upsun domain:add [--cert CERT] [--key KEY] [--chain CHAIN] [--attach ATTACH] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-W|--no-wait] [--wait] [--]
```
#### Arguments
* `name`(required)
The domain name
#### Options
* `--cert` (expects a value)
The path to a custom certificate file
* `--key` (expects a value)
The path to the private key for the custom certificate
* `--chain` (expects a value)
The path to the chain file(s) for the custom certificate
* `--attach` (expects a value)
The production domain that this one replaces in the environment's routes. Required for non-production environment domains.
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Add the domain example.com:
```
upsun domain:add example.com
```
* Add the domain example.org with a custom SSL/TLS certificate:
```
upsun domain:add example.org --cert example-org.crt --key example-org.key
```
## `domain:delete`
Delete a domain from the project
### Usage
```
upsun domain:delete [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-W|--no-wait] [--wait] [--]
```
#### Arguments
* `name`(required)
The domain name
#### Options
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Delete the domain example.com:
```
upsun domain:delete example.com
```
## `domain:get`
Show detailed information for a domain
### Usage
```
upsun domain:get [-P|--property PROPERTY] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [--date-fmt DATE-FMT] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--] []
```
#### Arguments
* `name`(optional)
The domain name
#### Options
* `--property` (`-P`) (expects a value)
The domain property to view
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `domain:list`
Get a list of all domains
Aliases: `domains`
### Usage
```
upsun domains [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [-p|--project PROJECT] [-e|--environment ENVIRONMENT]
```
#### Options
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: name*, ssl*, created_at*, registered_name, replacement_for, type, updated_at (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `domain:update`
Update a domain
### Usage
```
upsun domain:update [--cert CERT] [--key KEY] [--chain CHAIN] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-W|--no-wait] [--wait] [--]
```
#### Arguments
* `name`(required)
The domain name
#### Options
* `--cert` (expects a value)
The path to a custom certificate file
* `--key` (expects a value)
The path to the private key for the custom certificate
* `--chain` (expects a value)
The path to the chain file(s) for the custom certificate
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Update the custom certificate for the domain example.org:
```
upsun domain:update example.org --cert example-org.crt --key example-org.key
```
## `environment:activate`
Activate an environment
### Usage
```
upsun environment:activate [--parent PARENT] [--resources-init RESOURCES-INIT] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-W|--no-wait] [--wait] [--] []...
```
#### Arguments
* `environment`(optional; multiple values allowed)
The environment(s) to activate
#### Options
* `--parent` (expects a value)
Set a new environment parent before activating
* `--resources-init` (expects a value)
Set the resources to use for new services: parent, default or minimum. If not set, "parent" will be used.
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Activate the environments "develop" and "stage":
```
upsun environment:activate develop stage
```
## `environment:branch`
Branch an environment
Aliases: `branch`
### Usage
```
upsun branch [--title TITLE] [--type TYPE] [--no-clone-parent] [--no-checkout] [--resources-init RESOURCES-INIT] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-W|--no-wait] [--wait] [--] [] []
```
#### Arguments
* `id`(optional)
The ID (branch name) of the new environment
* `parent`(optional)
The parent of the new environment
#### Options
* `--title` (expects a value)
The title of the new environment
* `--type` (expects a value)
The type of the new environment
* `--no-clone-parent`
Do not clone the parent environment's data
* `--no-checkout`
Do not check out the branch locally
* `--resources-init` (expects a value)
Set the resources to use for new services: parent, default or minimum. If not set, "parent" will be used.
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Create a new branch "sprint-2", based on "develop":
```
upsun environment:branch sprint-2 develop
```
## `environment:checkout`
Check out an environment
Aliases: `checkout`
### Usage
```
upsun checkout []
```
#### Arguments
* `id`(optional)
The ID of the environment to check out. For example: "sprint2"
#### Options
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Check out the environment "develop":
```
upsun environment:checkout develop
```
## `environment:delete`
Delete one or more environments
### Usage
```
upsun environment:delete [--delete-branch] [--no-delete-branch] [--type TYPE] [-t|--only-type ONLY-TYPE] [--exclude EXCLUDE] [--exclude-type EXCLUDE-TYPE] [--inactive] [--status STATUS] [--only-status ONLY-STATUS] [--exclude-status EXCLUDE-STATUS] [--merged] [--allow-delete-parent] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-W|--no-wait] [--wait] [--] []...
```
When a Upsun environment is deleted, it will become "inactive": it will
exist only as a Git branch, containing code but no services, databases nor
files.
This command allows you to delete environments as well as their Git branches.
#### Arguments
* `environment`(optional; multiple values allowed)
The environment(s) to delete. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
#### Options
* `--delete-branch`
Delete Git branch(es) for inactive environments, without confirmation
* `--no-delete-branch`
Do not delete any Git branch(es) (inactive environments)
* `--type` (expects a value)
Delete all environments of a type (adding to any others selected) Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--only-type` (`-t`) (expects a value)
Only delete environments of a specific type Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--exclude` (expects a value)
Environment(s) not to delete. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--exclude-type` (expects a value)
Environment type(s) of which not to delete Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--inactive`
Delete all inactive environments (adding to any others selected)
* `--status` (expects a value)
Delete all environments of a status (adding to any others selected) Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--only-status` (expects a value)
Only delete environments of a specific status Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--exclude-status` (expects a value)
Environment status(es) of which not to delete Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--merged`
Delete all merged environments (adding to any others selected)
* `--allow-delete-parent`
Allow environments that have children to be deleted
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Delete the currently checked out environment:
```
upsun environment:delete
```
* Delete the environments "test" and "example-1":
```
upsun environment:delete test example-1
```
* Delete all inactive environments:
```
upsun environment:delete --inactive
```
* Delete all environments merged with their parent:
```
upsun environment:delete --merged
```
## `environment:drush`
Run a drush command on the remote environment
Aliases: `drush`
### Usage
```
upsun drush [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP] [--] []...
```
#### Arguments
* `cmd`(optional; multiple values allowed)
A command to pass to Drush
#### Options
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Run "drush status" on the remote environment:
```
upsun environment:drush status
```
* Enable the Overlay module on the remote environment:
```
upsun environment:drush en overlay
```
* Get a one-time login link (using -- before options):
```
upsun environment:drush user-login -- --mail=name@example.com
```
* Alternative syntax (quoting the whole command):
```
upsun environment:drush 'user-login --mail=name@example.com'
```
## `environment:http-access`
Update HTTP access settings for an environment
Aliases: `httpaccess`
### Usage
```
upsun httpaccess [--access ACCESS] [--auth AUTH] [--enabled ENABLED] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-W|--no-wait] [--wait]
```
#### Options
* `--access` (expects a value)
Access restriction in the format "permission:address". Use 0 to clear all addresses.
* `--auth` (expects a value)
HTTP Basic auth credentials in the format "username:password". Use 0 to clear all credentials.
* `--enabled` (expects a value)
Whether access control should be enabled: 1 to enable, 0 to disable
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Require a username and password:
```
upsun environment:http-access --auth myname:mypassword
```
* Restrict access to only one IP address:
```
upsun environment:http-access --access allow:69.208.1.192 --access deny:any
```
* Remove the password requirement, keeping IP restrictions:
```
upsun environment:http-access --auth 0
```
* Disable all HTTP access control:
```
upsun environment:http-access --enabled 0
```
## `environment:info`
Read or set properties for an environment
### Usage
```
upsun environment:info [--refresh] [--date-fmt DATE-FMT] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-W|--no-wait] [--wait] [--] [] []
```
#### Arguments
* `property`(optional)
The name of the property
* `value`(optional)
Set a new value for the property
#### Options
* `--refresh`
Whether to refresh the cache
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Read all environment properties:
```
upsun environment:info
```
* Show the environment's status:
```
upsun environment:info status
```
* Show the date the environment was created:
```
upsun environment:info created_at
```
* Enable email sending:
```
upsun environment:info enable_smtp true
```
* Change the environment title:
```
upsun environment:info title "New feature"
```
* Change the environment's parent branch:
```
upsun environment:info parent sprint-2
```
* Unset the environment's parent branch:
```
upsun environment:info parent -
```
## `environment:init`
Initialize an environment from a public Git repository
### Usage
```
upsun environment:init [--profile PROFILE] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-W|--no-wait] [--wait] [--]
```
#### Arguments
* `url`(required)
A URL to a Git repository
#### Options
* `--profile` (expects a value)
The name of the profile
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `environment:list`
Get a list of environments
Aliases: `environments`, `env`
### Usage
```
upsun environments [-I|--no-inactive] [--status STATUS] [--pipe] [--refresh REFRESH] [--sort SORT] [--reverse] [--type TYPE] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [-p|--project PROJECT]
```
#### Options
* `--no-inactive` (`-I`)
Do not show inactive environments
* `--status` (expects a value)
Filter environments by status (active, inactive, dirty, paused, deleting). Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--pipe`
Output a simple list of environment IDs.
* `--refresh` (expects a value)
Whether to refresh the list.
* `--sort` (expects a value)
A property to sort by
* `--reverse`
Sort in reverse (descending) order
* `--type` (expects a value)
Filter the list by environment type(s). Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: id*, title*, status*, type*, created, machine_name, updated (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `environment:logs`
Read an environment's logs
Aliases: `log`
### Usage
```
upsun log [--lines LINES] [--tail] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP] [--worker WORKER] [-I|--instance INSTANCE] [--] []
```
#### Arguments
* `type`(optional)
The log type, e.g. "access" or "error"
#### Options
* `--lines` (expects a value)
The number of lines to show
* `--tail`
Continuously tail the log
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--worker` (expects a value)
A worker name
* `--instance` (`-I`) (expects a value)
An instance ID
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Display a choice of logs that can be read:
```
upsun environment:logs
```
* Read the deploy log:
```
upsun environment:logs deploy
```
* Read the access log continuously:
```
upsun environment:logs access --tail
```
* Read the last 500 lines of the cron log:
```
upsun environment:logs cron --lines 500
```
## `environment:merge`
Merge an environment
Aliases: `merge`
### Usage
```
upsun merge [--resources-init RESOURCES-INIT] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-W|--no-wait] [--wait] [--] []
```
This command will initiate a Git merge of the specified environment into its parent environment.
#### Arguments
* `environment`(optional)
The environment to merge
#### Options
* `--resources-init` (expects a value)
Set the resources to use for new services: child, default, minimum or manual. If not set, "child" will be used.
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Merge the environment "sprint-2" into its parent:
```
upsun environment:merge sprint-2
```
## `environment:pause`
Pause an environment
### Usage
```
upsun environment:pause [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-W|--no-wait] [--wait]
```
Pausing an environment helps to reduce resource consumption and carbon emissions.
The environment will be unavailable until it is resumed. No data will be lost.
#### Options
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `environment:push`
Push code to an environment
Aliases: `push`
### Usage
```
upsun push [--target TARGET] [-f|--force] [--force-with-lease] [-u|--set-upstream] [--activate] [--parent PARENT] [--type TYPE] [--no-clone-parent] [--resources-init RESOURCES-INIT] [-W|--no-wait] [--wait] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--] []
```
#### Arguments
* `source`(optional)
The Git source ref, e.g. a branch name or a commit hash.
#### Options
* `--target` (expects a value)
The target branch name. Defaults to the current branch.
* `--force` (`-f`)
Allow non-fast-forward updates
* `--force-with-lease`
Allow non-fast-forward updates, if the remote-tracking branch is up to date
* `--set-upstream` (`-u`)
Set the target environment as the upstream for the source branch. This will also set the target project as the remote for the local repository.
* `--activate`
Activate the environment. Paused environments will be resumed. This will ensure the environment is active even if no changes were pushed.
* `--parent` (expects a value)
Set the environment parent (only used with --activate)
* `--type` (expects a value)
Set the environment type (only used with --activate )
* `--no-clone-parent`
Do not clone the parent branch's data (only used with --activate)
* `--resources-init` (expects a value)
Set the resources to use for new services: parent, default, minimum, or manual. Currently the default is "default" but this will change to "parent" in future.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Push code to the current environment:
```
upsun environment:push
```
* Push code, without waiting for deployment:
```
upsun environment:push --no-wait
```
* Push code, branching or activating the environment as a child of 'develop':
```
upsun environment:push --activate --parent develop
```
## `environment:redeploy`
Redeploy an environment
Aliases: `redeploy`
### Usage
```
upsun redeploy [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-W|--no-wait] [--wait]
```
#### Options
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `environment:relationships`
Show an environment's relationships
Aliases: `relationships`, `rel`
### Usage
```
upsun relationships [-P|--property PROPERTY] [--refresh] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP] [--] []
```
#### Arguments
* `environment`(optional)
The environment
#### Options
* `--property` (`-P`) (expects a value)
The relationship property to view
* `--refresh`
Whether to refresh the relationships
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* View all the current environment's relationships:
```
upsun environment:relationships
```
* View the 'main' environment's relationships:
```
upsun environment:relationships main
```
* View the 'main' environment's database port:
```
upsun environment:relationships main --property database.0.port
```
## `environment:resume`
Resume a paused environment
### Usage
```
upsun environment:resume [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-W|--no-wait] [--wait]
```
#### Options
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `environment:scp`
Copy files to and from an environment using scp
Aliases: `scp`
### Usage
```
upsun scp [-r|--recursive] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP] [--worker WORKER] [-I|--instance INSTANCE] [--] []...
```
#### Arguments
* `files`(optional; multiple values allowed)
Files to copy. Use the remote: prefix to define remote locations.
#### Options
* `--recursive` (`-r`)
Recursively copy entire directories
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--worker` (expects a value)
A worker name
* `--instance` (`-I`) (expects a value)
An instance ID
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Copy local files a.txt and b.txt to remote mount var/files:
```
upsun environment:scp a.txt b.txt remote:var/files
```
* Copy remote files c.txt to current directory:
```
upsun environment:scp remote:c.txt .
```
* Copy subdirectory dump/ to remote mount var/files:
```
upsun environment:scp -r dump remote:var/logs
```
* Copy files inside subdirectory dump/ to remote mount var/files:
```
upsun environment:scp -r dump/* remote:var/logs
```
## `environment:ssh`
SSH to the current environment
Aliases: `ssh`
### Usage
```
upsun ssh [--pipe] [--all] [-o|--option OPTION] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP] [--worker WORKER] [-I|--instance INSTANCE] [--] []...
```
#### Arguments
* `cmd`(optional; multiple values allowed)
A command to run on the environment.
#### Options
* `--pipe`
Output the SSH URL only.
* `--all`
Output all SSH URLs (for every app).
* `--option` (`-o`) (expects a value)
Pass an extra option to SSH
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--worker` (expects a value)
A worker name
* `--instance` (`-I`) (expects a value)
An instance ID
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Open a shell over SSH:
```
upsun environment:ssh
```
* Pass an extra option to SSH:
```
upsun environment:ssh -o 'RequestTTY force'
```
* List files:
```
upsun environment:ssh ls
```
* Monitor the app log (use '--' before flags):
```
upsun environment:ssh tail /var/log/app.log -- -n50 -f
```
* Display relationships (use quotes for complex syntax):
```
upsun environment:ssh 'echo $PLATFORM_RELATIONSHIPS | base64 --decode'
```
## `environment:synchronize`
Synchronize an environment's code, data and/or resources from its parent
Aliases: `sync`
### Usage
```
upsun sync [--rebase] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-W|--no-wait] [--wait] [--] []...
```
This command synchronizes to a child environment from its parent environment.
Synchronizing "code" means there will be a Git merge from the parent to the
child.
Synchronizing "data" means that all files in all services (including
static files, databases, logs, search indices, etc.) will be copied from the
parent to the child.
Synchronizing "resources" means that the parent environment's resource sizes
will be used for all corresponding apps and services in the child environment.
#### Arguments
* `synchronize`(optional; multiple values allowed)
List what to synchronize: "code", "data", and/or "resources".
#### Options
* `--rebase`
Synchronize code by rebasing instead of merging
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Synchronize data from the parent environment:
```
upsun environment:synchronize data
```
* Synchronize code and data from the parent environment:
```
upsun environment:synchronize code data
```
* Synchronize code, data and resources from the parent environment:
```
upsun environment:synchronize code data resources
```
## `environment:url`
Get the public URLs of an environment
Aliases: `url`
### Usage
```
upsun url [-1|--primary] [--browser BROWSER] [--pipe] [-p|--project PROJECT] [-e|--environment ENVIRONMENT]
```
#### Options
* `--primary` (`-1`)
Only return the URL for the primary route
* `--browser` (expects a value)
The browser to use to open the URL. Set 0 for none.
* `--pipe`
Output the URL to stdout.
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Give a choice of URLs to open (or print all URLs if there is no browser):
```
upsun environment:url
```
* Print all URLs:
```
upsun environment:url --pipe
```
* Print and/or open the primary route URL:
```
upsun environment:url --primary
```
* Print the primary route URL:
```
upsun environment:url --primary --pipe
```
## `environment:xdebug`
Open a tunnel to Xdebug on the environment
Aliases: `xdebug`
### Usage
```
upsun xdebug [--port PORT] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP] [--worker WORKER] [-I|--instance INSTANCE]
```
#### Options
* `--port` (expects a value)
The local port
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--worker` (expects a value)
A worker name
* `--instance` (`-I`) (expects a value)
An instance ID
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Connect to Xdebug on the environment, listening locally on port 9000.:
```
upsun environment:xdebug
```
## `integration:activity:get`
View detailed information on a single integration activity
### Usage
```
upsun integration:activity:get [-P|--property PROPERTY] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [--date-fmt DATE-FMT] [--] [] []
```
#### Arguments
* `integration`(optional)
An integration ID. Leave blank to choose from a list.
* `activity`(optional)
The activity ID. Defaults to the most recent integration activity.
#### Options
* `--property` (`-P`) (expects a value)
The property to view
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
[Deprecated option, not used]
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `integration:activity:list`
Get a list of activities for an integration
Aliases: `integration:activities`
### Usage
```
upsun integration:activities [--type TYPE] [-x|--exclude-type EXCLUDE-TYPE] [--limit LIMIT] [--start START] [--state STATE] [--result RESULT] [-i|--incomplete] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [--date-fmt DATE-FMT] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--] []
```
#### Arguments
* `id`(optional)
An integration ID. Leave blank to choose from a list.
#### Options
* `--type` (expects a value)
Filter activities by type. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--exclude-type` (`-x`) (expects a value)
Exclude activities by type. Values may be split by commas (e.g. "a,b,c") and/or whitespace. The % or * characters can be used as a wildcard to exclude types.
* `--limit` (expects a value)
Limit the number of results displayed
* `--start` (expects a value)
Only activities created before this date will be listed
* `--state` (expects a value)
Filter activities by state. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--result` (expects a value)
Filter activities by result
* `--incomplete` (`-i`)
Only list incomplete activities
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: id*, created*, description*, type*, state*, result*, completed, progress, time_build, time_deploy, time_execute, time_wait (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
[Deprecated option, not used]
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `integration:activity:log`
Display the log for an integration activity
### Usage
```
upsun integration:activity:log [-t|--timestamps] [--date-fmt DATE-FMT] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--] [] []
```
#### Arguments
* `integration`(optional)
An integration ID. Leave blank to choose from a list.
* `activity`(optional)
The activity ID. Defaults to the most recent integration activity.
#### Options
* `--timestamps` (`-t`)
Display a timestamp next to each message
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
[Deprecated option, not used]
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `integration:add`
Add an integration to the project
### Usage
```
upsun integration:add [--type TYPE] [--base-url BASE-URL] [--bitbucket-url BITBUCKET-URL] [--username USERNAME] [--token TOKEN] [--key KEY] [--secret SECRET] [--license-key LICENSE-KEY] [--server-project SERVER-PROJECT] [--repository REPOSITORY] [--build-merge-requests BUILD-MERGE-REQUESTS] [--build-pull-requests BUILD-PULL-REQUESTS] [--build-draft-pull-requests BUILD-DRAFT-PULL-REQUESTS] [--build-pull-requests-post-merge BUILD-PULL-REQUESTS-POST-MERGE] [--build-wip-merge-requests BUILD-WIP-MERGE-REQUESTS] [--merge-requests-clone-parent-data MERGE-REQUESTS-CLONE-PARENT-DATA] [--pull-requests-clone-parent-data PULL-REQUESTS-CLONE-PARENT-DATA] [--resync-pull-requests RESYNC-PULL-REQUESTS] [--fetch-branches FETCH-BRANCHES] [--prune-branches PRUNE-BRANCHES] [--resources-init RESOURCES-INIT] [--url URL] [--shared-key SHARED-KEY] [--file FILE] [--events EVENTS] [--states STATES] [--environments ENVIRONMENTS] [--excluded-environments EXCLUDED-ENVIRONMENTS] [--from-address FROM-ADDRESS] [--recipients RECIPIENTS] [--channel CHANNEL] [--routing-key ROUTING-KEY] [--category CATEGORY] [--index INDEX] [--sourcetype SOURCETYPE] [--protocol PROTOCOL] [--syslog-host SYSLOG-HOST] [--syslog-port SYSLOG-PORT] [--facility FACILITY] [--message-format MESSAGE-FORMAT] [--auth-mode AUTH-MODE] [--auth-token AUTH-TOKEN] [--verify-tls VERIFY-TLS] [--header HEADER] [-p|--project PROJECT] [-W|--no-wait] [--wait]
```
#### Options
* `--type` (expects a value)
The integration type ('bitbucket', 'bitbucket_server', 'github', 'gitlab', 'webhook', 'health.email', 'health.pagerduty', 'health.slack', 'health.webhook', 'httplog', 'script', 'newrelic', 'splunk', 'sumologic', 'syslog')
* `--base-url` (expects a value)
The base URL of the server installation
* `--bitbucket-url` (expects a value)
The base URL of the Bitbucket Server installation
* `--username` (expects a value)
The Bitbucket Server username
* `--token` (expects a value)
An authentication or access token for the integration
* `--key` (expects a value)
A Bitbucket OAuth consumer key
* `--secret` (expects a value)
A Bitbucket OAuth consumer secret
* `--license-key` (expects a value)
The New Relic Logs license key
* `--server-project` (expects a value)
The project (e.g. 'namespace/repo')
* `--repository` (expects a value)
The repository to track (e.g. 'owner/repository')
* `--build-merge-requests` (expects a value)
GitLab: build merge requests as environments
* `--build-pull-requests` (expects a value)
Build every pull request as an environment
* `--build-draft-pull-requests` (expects a value)
Build draft pull requests
* `--build-pull-requests-post-merge` (expects a value)
Build pull requests based on their post-merge state
* `--build-wip-merge-requests` (expects a value)
GitLab: build WIP merge requests
* `--merge-requests-clone-parent-data` (expects a value)
GitLab: clone data for merge requests
* `--pull-requests-clone-parent-data` (expects a value)
Clone the parent environment's data for pull requests
* `--resync-pull-requests` (expects a value)
Re-sync pull request environment data on every build
* `--fetch-branches` (expects a value)
Fetch all branches from the remote (as inactive environments)
* `--prune-branches` (expects a value)
Delete branches that do not exist on the remote
* `--resources-init` (expects a value)
The resources to use when initializing a new service ('minimum', 'default', 'manual', 'parent')
* `--url` (expects a value)
The URL or API endpoint for the integration
* `--shared-key` (expects a value)
Webhook: the JWS shared secret key
* `--file` (expects a value)
The name of a local file that contains the script to upload
* `--events` (expects a value)
A list of events to act on, e.g. environment.push
* `--states` (expects a value)
A list of states to act on, e.g. pending, in_progress, complete
* `--environments` (expects a value)
The environment IDs to include
* `--excluded-environments` (expects a value)
The environment IDs to exclude
* `--from-address` (expects a value)
[Optional] Custom From address for alert emails
* `--recipients` (expects a value)
The recipient email address(es)
* `--channel` (expects a value)
The Slack channel
* `--routing-key` (expects a value)
The PagerDuty routing key
* `--category` (expects a value)
The Sumo Logic category, used for filtering
* `--index` (expects a value)
The Splunk index
* `--sourcetype` (expects a value)
The Splunk event source type
* `--protocol` (expects a value)
Syslog transport protocol ('tcp', 'udp', 'tls')
* `--syslog-host` (expects a value)
Syslog relay/collector host
* `--syslog-port` (expects a value)
Syslog relay/collector port
* `--facility` (expects a value)
Syslog facility
* `--message-format` (expects a value)
Syslog message format ('rfc3164' or 'rfc5424')
* `--auth-mode` (expects a value)
Authentication mode ('prefix' or 'structured_data')
* `--auth-token` (expects a value)
Authentication token
* `--verify-tls` (expects a value)
Whether HTTPS certificate verification should be enabled (recommended)
* `--header` (expects a value)
HTTP header(s) to use in POST requests. Separate names and values with a colon (:).
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Add an integration with a GitHub repository:
```
upsun integration:add --type github --repository myuser/example-repo --token 9218376e14c2797e0d06e8d2f918d45f --fetch-branches 0
```
* Add an integration with a GitLab repository:
```
upsun integration:add --type gitlab --server-project mygroup/example-repo --token 22fe4d70dfbc20e4f668568a0b5422e2 --base-url https://gitlab.example.com
```
## `integration:delete`
Delete an integration from a project
### Usage
```
upsun integration:delete [-p|--project PROJECT] [-W|--no-wait] [--wait] [--] []
```
#### Arguments
* `id`(optional)
The integration ID. Leave blank to choose from a list.
#### Options
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `integration:get`
View details of an integration
### Usage
```
upsun integration:get [-P|--property [PROPERTY]] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [-p|--project PROJECT] [--] []
```
#### Arguments
* `id`(optional)
An integration ID. Leave blank to choose from a list.
#### Options
* `--property` (`-P`) (expects a value)
The integration property to view
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `integration:list`
View a list of project integration(s)
Aliases: `integrations`
### Usage
```
upsun integrations [-t|--type TYPE] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [-p|--project PROJECT]
```
#### Options
* `--type` (`-t`) (expects a value)
Filter by type
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: id, summary, type. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `integration:update`
Update an integration
### Usage
```
upsun integration:update [--type TYPE] [--base-url BASE-URL] [--bitbucket-url BITBUCKET-URL] [--username USERNAME] [--token TOKEN] [--key KEY] [--secret SECRET] [--license-key LICENSE-KEY] [--server-project SERVER-PROJECT] [--repository REPOSITORY] [--build-merge-requests BUILD-MERGE-REQUESTS] [--build-pull-requests BUILD-PULL-REQUESTS] [--build-draft-pull-requests BUILD-DRAFT-PULL-REQUESTS] [--build-pull-requests-post-merge BUILD-PULL-REQUESTS-POST-MERGE] [--build-wip-merge-requests BUILD-WIP-MERGE-REQUESTS] [--merge-requests-clone-parent-data MERGE-REQUESTS-CLONE-PARENT-DATA] [--pull-requests-clone-parent-data PULL-REQUESTS-CLONE-PARENT-DATA] [--resync-pull-requests RESYNC-PULL-REQUESTS] [--fetch-branches FETCH-BRANCHES] [--prune-branches PRUNE-BRANCHES] [--resources-init RESOURCES-INIT] [--url URL] [--shared-key SHARED-KEY] [--file FILE] [--events EVENTS] [--states STATES] [--environments ENVIRONMENTS] [--excluded-environments EXCLUDED-ENVIRONMENTS] [--from-address FROM-ADDRESS] [--recipients RECIPIENTS] [--channel CHANNEL] [--routing-key ROUTING-KEY] [--category CATEGORY] [--index INDEX] [--sourcetype SOURCETYPE] [--protocol PROTOCOL] [--syslog-host SYSLOG-HOST] [--syslog-port SYSLOG-PORT] [--facility FACILITY] [--message-format MESSAGE-FORMAT] [--auth-mode AUTH-MODE] [--auth-token AUTH-TOKEN] [--verify-tls VERIFY-TLS] [--header HEADER] [-p|--project PROJECT] [-W|--no-wait] [--wait] [--] []
```
#### Arguments
* `id`(optional)
The ID of the integration to update
#### Options
* `--type` (expects a value)
The integration type ('bitbucket', 'bitbucket_server', 'github', 'gitlab', 'webhook', 'health.email', 'health.pagerduty', 'health.slack', 'health.webhook', 'httplog', 'script', 'newrelic', 'splunk', 'sumologic', 'syslog')
* `--base-url` (expects a value)
The base URL of the server installation
* `--bitbucket-url` (expects a value)
The base URL of the Bitbucket Server installation
* `--username` (expects a value)
The Bitbucket Server username
* `--token` (expects a value)
An authentication or access token for the integration
* `--key` (expects a value)
A Bitbucket OAuth consumer key
* `--secret` (expects a value)
A Bitbucket OAuth consumer secret
* `--license-key` (expects a value)
The New Relic Logs license key
* `--server-project` (expects a value)
The project (e.g. 'namespace/repo')
* `--repository` (expects a value)
The repository to track (e.g. 'owner/repository')
* `--build-merge-requests` (expects a value)
GitLab: build merge requests as environments
* `--build-pull-requests` (expects a value)
Build every pull request as an environment
* `--build-draft-pull-requests` (expects a value)
Build draft pull requests
* `--build-pull-requests-post-merge` (expects a value)
Build pull requests based on their post-merge state
* `--build-wip-merge-requests` (expects a value)
GitLab: build WIP merge requests
* `--merge-requests-clone-parent-data` (expects a value)
GitLab: clone data for merge requests
* `--pull-requests-clone-parent-data` (expects a value)
Clone the parent environment's data for pull requests
* `--resync-pull-requests` (expects a value)
Re-sync pull request environment data on every build
* `--fetch-branches` (expects a value)
Fetch all branches from the remote (as inactive environments)
* `--prune-branches` (expects a value)
Delete branches that do not exist on the remote
* `--resources-init` (expects a value)
The resources to use when initializing a new service ('minimum', 'default', 'manual', 'parent')
* `--url` (expects a value)
The URL or API endpoint for the integration
* `--shared-key` (expects a value)
Webhook: the JWS shared secret key
* `--file` (expects a value)
The name of a local file that contains the script to upload
* `--events` (expects a value)
A list of events to act on, e.g. environment.push
* `--states` (expects a value)
A list of states to act on, e.g. pending, in_progress, complete
* `--environments` (expects a value)
The environment IDs to include
* `--excluded-environments` (expects a value)
The environment IDs to exclude
* `--from-address` (expects a value)
[Optional] Custom From address for alert emails
* `--recipients` (expects a value)
The recipient email address(es)
* `--channel` (expects a value)
The Slack channel
* `--routing-key` (expects a value)
The PagerDuty routing key
* `--category` (expects a value)
The Sumo Logic category, used for filtering
* `--index` (expects a value)
The Splunk index
* `--sourcetype` (expects a value)
The Splunk event source type
* `--protocol` (expects a value)
Syslog transport protocol ('tcp', 'udp', 'tls')
* `--syslog-host` (expects a value)
Syslog relay/collector host
* `--syslog-port` (expects a value)
Syslog relay/collector port
* `--facility` (expects a value)
Syslog facility
* `--message-format` (expects a value)
Syslog message format ('rfc3164' or 'rfc5424')
* `--auth-mode` (expects a value)
Authentication mode ('prefix' or 'structured_data')
* `--auth-token` (expects a value)
Authentication token
* `--verify-tls` (expects a value)
Whether HTTPS certificate verification should be enabled (recommended)
* `--header` (expects a value)
HTTP header(s) to use in POST requests. Separate names and values with a colon (:).
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Switch on the "fetch branches" option for a specific integration:
```
upsun integration:update ZXhhbXBsZSB --fetch-branches 1
```
## `integration:validate`
Validate an existing integration
### Usage
```
upsun integration:validate [-p|--project PROJECT] [--] []
```
This command allows you to check whether an integration is valid.
An exit code of 0 means the integration is valid, while 4 means it is invalid.
Any other exit code indicates an unexpected error.
Integrations are validated automatically on creation and on update. However,
because they involve external resources, it is possible for a valid integration
to become invalid. For example, an access token may be revoked, or an external
repository may be deleted.
#### Arguments
* `id`(optional)
An integration ID. Leave blank to choose from a list.
#### Options
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `local:dir`
Find the local project root
Aliases: `dir`
### Usage
```
upsun dir []
```
#### Arguments
* `subdir`(optional)
The subdirectory to find ('local', 'web' or 'shared')
#### Options
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `metrics:all`
Show CPU, disk and memory metrics for an environment
Aliases: `metrics`, `met`
### Usage
```
upsun metrics [-B|--bytes] [-r|--range RANGE] [-i|--interval INTERVAL] [--to TO] [-1|--latest] [-s|--service SERVICE] [--type TYPE] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [--date-fmt DATE-FMT]
```
#### Options
* `--bytes` (`-B`)
Show sizes in bytes
* `--range` (`-r`) (expects a value)
The time range. Metrics will be loaded for this duration until the end time (--to). You can specify units: hours (h), minutes (m), or seconds (s). Minimum 5m, maximum 8h or more (depending on the project), default 10m.
* `--interval` (`-i`) (expects a value)
The time interval. Defaults to a division of the range. You can specify units: hours (h), minutes (m), or seconds (s). Minimum 1m.
* `--to` (expects a value)
The end time. Defaults to now.
* `--latest` (`-1`)
Show only the latest single data point
* `--service` (`-s`) (expects a value)
Filter by service or application name The % or * characters may be used as a wildcard.
* `--type` (expects a value)
Filter by service type (if --service is not provided). The version is not required. The % or * characters may be used as a wildcard.
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: timestamp*, service*, cpu_percent*, mem_percent*, disk_percent*, tmp_disk_percent*, cpu_limit, cpu_used, disk_limit, disk_used, inodes_limit, inodes_percent, inodes_used, mem_limit, mem_used, tmp_disk_limit, tmp_disk_used, tmp_inodes_limit, tmp_inodes_percent, tmp_inodes_used, type (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Show metrics for the last 10m:
```
upsun metrics:all
```
* Show metrics in five-minute intervals over the last hour:
```
upsun metrics:all -i 5m -r 1h
```
* Show metrics for all SQL services:
```
upsun metrics:all --type mariadb,%sql
```
## `metrics:cpu`
Show CPU usage of an environment
Aliases: `cpu`
### Usage
```
upsun cpu [-r|--range RANGE] [-i|--interval INTERVAL] [--to TO] [-1|--latest] [-s|--service SERVICE] [--type TYPE] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [--date-fmt DATE-FMT]
```
#### Options
* `--range` (`-r`) (expects a value)
The time range. Metrics will be loaded for this duration until the end time (--to). You can specify units: hours (h), minutes (m), or seconds (s). Minimum 5m, maximum 8h or more (depending on the project), default 10m.
* `--interval` (`-i`) (expects a value)
The time interval. Defaults to a division of the range. You can specify units: hours (h), minutes (m), or seconds (s). Minimum 1m.
* `--to` (expects a value)
The end time. Defaults to now.
* `--latest` (`-1`)
Show only the latest single data point
* `--service` (`-s`) (expects a value)
Filter by service or application name The % or * characters may be used as a wildcard.
* `--type` (expects a value)
Filter by service type (if --service is not provided). The version is not required. The % or * characters may be used as a wildcard.
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: timestamp*, service*, used*, limit*, percent*, type (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `metrics:disk-usage`
Show disk usage of an environment
Aliases: `disk`
### Usage
```
upsun disk [-B|--bytes] [-r|--range RANGE] [-i|--interval INTERVAL] [--to TO] [-1|--latest] [-s|--service SERVICE] [--type TYPE] [--tmp] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [--date-fmt DATE-FMT]
```
#### Options
* `--bytes` (`-B`)
Show sizes in bytes
* `--range` (`-r`) (expects a value)
The time range. Metrics will be loaded for this duration until the end time (--to). You can specify units: hours (h), minutes (m), or seconds (s). Minimum 5m, maximum 8h or more (depending on the project), default 10m.
* `--interval` (`-i`) (expects a value)
The time interval. Defaults to a division of the range. You can specify units: hours (h), minutes (m), or seconds (s). Minimum 1m.
* `--to` (expects a value)
The end time. Defaults to now.
* `--latest` (`-1`)
Show only the latest single data point
* `--service` (`-s`) (expects a value)
Filter by service or application name The % or * characters may be used as a wildcard.
* `--type` (expects a value)
Filter by service type (if --service is not provided). The version is not required. The % or * characters may be used as a wildcard.
* `--tmp`
Report temporary disk usage (shows columns: timestamp, service, tmp_used, tmp_limit, tmp_percent, tmp_ipercent)
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: timestamp*, service*, used*, limit*, percent*, ipercent*, tmp_percent*, ilimit, iused, tmp_ilimit, tmp_ipercent, tmp_iused, tmp_limit, tmp_used, type (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `metrics:memory`
Show memory usage of an environment
Aliases: `mem`, `memory`
### Usage
```
upsun mem [-B|--bytes] [-r|--range RANGE] [-i|--interval INTERVAL] [--to TO] [-1|--latest] [-s|--service SERVICE] [--type TYPE] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [--date-fmt DATE-FMT]
```
#### Options
* `--bytes` (`-B`)
Show sizes in bytes
* `--range` (`-r`) (expects a value)
The time range. Metrics will be loaded for this duration until the end time (--to). You can specify units: hours (h), minutes (m), or seconds (s). Minimum 5m, maximum 8h or more (depending on the project), default 10m.
* `--interval` (`-i`) (expects a value)
The time interval. Defaults to a division of the range. You can specify units: hours (h), minutes (m), or seconds (s). Minimum 1m.
* `--to` (expects a value)
The end time. Defaults to now.
* `--latest` (`-1`)
Show only the latest single data point
* `--service` (`-s`) (expects a value)
Filter by service or application name The % or * characters may be used as a wildcard.
* `--type` (expects a value)
Filter by service type (if --service is not provided). The version is not required. The % or * characters may be used as a wildcard.
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: timestamp*, service*, used*, limit*, percent*, type (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `mount:download`
Download files from a mount, using rsync
### Usage
```
upsun mount:download [-a|--all] [-m|--mount MOUNT] [--target TARGET] [--source-path] [--delete] [--exclude EXCLUDE] [--include INCLUDE] [--refresh] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP] [--worker WORKER] [-I|--instance INSTANCE]
```
#### Options
* `--all` (`-a`)
Download from all mounts
* `--mount` (`-m`) (expects a value)
The mount (as an app-relative path)
* `--target` (expects a value)
The directory to which files will be downloaded. If --all is used, the mount path will be appended
* `--source-path`
Use the mount's source path (rather than the mount path) as a subdirectory of the target, when --all is used
* `--delete`
Whether to delete extraneous files in the target directory
* `--exclude` (expects a value)
File(s) to exclude from the download (pattern)
* `--include` (expects a value)
File(s) not to exclude (pattern)
* `--refresh`
Whether to refresh the cache
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--worker` (expects a value)
A worker name
* `--instance` (`-I`) (expects a value)
An instance ID
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `mount:list`
Get a list of mounts
Aliases: `mounts`
### Usage
```
upsun mounts [--paths] [--refresh] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP] [--worker WORKER] [-I|--instance INSTANCE]
```
#### Options
* `--paths`
Output the mount paths only (one per line)
* `--refresh`
Whether to refresh the cache
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: definition, path. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--worker` (expects a value)
A worker name
* `--instance` (`-I`) (expects a value)
An instance ID
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `mount:upload`
Upload files to a mount, using rsync
### Usage
```
upsun mount:upload [--source SOURCE] [-m|--mount MOUNT] [--delete] [--exclude EXCLUDE] [--include INCLUDE] [--refresh] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP] [--worker WORKER] [-I|--instance INSTANCE]
```
#### Options
* `--source` (expects a value)
A directory containing files to upload
* `--mount` (`-m`) (expects a value)
The mount (as an app-relative path)
* `--delete`
Whether to delete extraneous files in the mount
* `--exclude` (expects a value)
File(s) to exclude from the upload (pattern)
* `--include` (expects a value)
File(s) not to exclude (pattern)
* `--refresh`
Whether to refresh the cache
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--worker` (expects a value)
A worker name
* `--instance` (`-I`) (expects a value)
An instance ID
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `operation:list`
List runtime operations on an environment
Aliases: `ops`
### Usage
```
upsun ops [--full] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP] [--worker WORKER] [--format FORMAT] [-c|--columns COLUMNS] [--no-header]
```
#### Options
* `--full`
Do not limit the length of command to display. The default limit is 24 lines.
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--worker` (expects a value)
A worker name
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: service*, name*, start*, role, stop (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `operation:run`
Run an operation on the environment
### Usage
```
upsun operation:run [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP] [--worker WORKER] [-W|--no-wait] [--wait] [--] []
```
#### Arguments
* `operation`(optional)
The operation name
#### Options
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--worker` (expects a value)
A worker name
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `organization:billing:address`
View or change an organization's billing address
### Usage
```
upsun organization:billing:address [-o|--org ORG] [-p|--project PROJECT] [--date-fmt DATE-FMT] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [--] [] [] []...
```
#### Arguments
* `property`(optional)
The name of a property to view or change
* `value`(optional)
A new value for the property
* `properties`(optional; multiple values allowed)
Additional property/value pairs
#### Options
* `--org` (`-o`) (expects a value)
The organization name (or ID)
* `--project` (`-p`) (expects a value)
The project ID or URL, to auto-select the organization if --org is not used
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `organization:billing:profile`
View or change an organization's billing profile
### Usage
```
upsun organization:billing:profile [-o|--org ORG] [-p|--project PROJECT] [--date-fmt DATE-FMT] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [--] [] []
```
#### Arguments
* `property`(optional)
The name of a property to view or change
* `value`(optional)
A new value for the property
#### Options
* `--org` (`-o`) (expects a value)
The organization name (or ID)
* `--project` (`-p`) (expects a value)
The project ID or URL, to auto-select the organization if --org is not used
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `organization:create`
Create a new organization
### Usage
```
upsun organization:create [--label LABEL] [--name NAME] [--country COUNTRY]
```
Organizations allow you to manage your Upsun projects, users and billing. Projects are owned by organizations.
You can add other users to your organization, for collaboratively managing the organization as well as its projects and billing information.
Access to individual projects (API and SSH) is managed separately, for now.
#### Options
* `--label` (expects a value)
The full name of the organization, e.g. "ACME Inc."
* `--name` (expects a value)
The organization machine name, used for URL paths and similar purposes.
* `--country` (expects a value)
The organization country. Used as the default for the billing address.
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `organization:delete`
Delete an organization
### Usage
```
upsun organization:delete [-o|--org ORG] [-p|--project PROJECT]
```
#### Options
* `--org` (`-o`) (expects a value)
The organization name (or ID)
* `--project` (`-p`) (expects a value)
The project ID or URL, to auto-select the organization if --org is not used
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `organization:info`
View or change organization details
### Usage
```
upsun organization:info [-o|--org ORG] [-p|--project PROJECT] [--date-fmt DATE-FMT] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [--] [] []
```
#### Arguments
* `property`(optional)
The name of a property to view or change
* `value`(optional)
A new value for the property
#### Options
* `--org` (`-o`) (expects a value)
The organization name (or ID)
* `--project` (`-p`) (expects a value)
The project ID or URL, to auto-select the organization if --org is not used
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* View the organization "acme":
```
upsun organization:info --org acme
```
* Show the organization's label:
```
upsun organization:info --org acme label
```
* Change the organization label:
```
upsun organization:info --org acme label "ACME Inc."
```
## `organization:list`
List organizations
Aliases: `orgs`, `organizations`
### Usage
```
upsun orgs [--my] [--sort SORT] [--reverse] [--format FORMAT] [-c|--columns COLUMNS] [--no-header]
```
#### Options
* `--my`
List only the organizations you own
* `--sort` (expects a value)
An organization property to sort by
* `--reverse`
Sort in reverse order
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: name*, label*, owner_email*, created_at, id, owner_id, owner_username, updated_at (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `organization:subscription:list`
List subscriptions within an organization
Aliases: `org:subs`
### Usage
```
upsun org:subs [--page PAGE] [-c|--count COUNT] [-o|--org ORG] [-p|--project PROJECT] [--format FORMAT] [--columns COLUMNS] [--no-header]
```
#### Options
* `--page` (expects a value)
Page number. This enables pagination, despite configuration or --count.
* `--count` (`-c`) (expects a value)
The number of items to display per page. Use 0 to disable pagination. Ignored if --page is specified.
* `--org` (`-o`) (expects a value)
The organization name (or ID)
* `--project` (`-p`) (expects a value)
The project ID or URL, to auto-select the organization if --org is not used
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (expects a value)
Columns to display. Available columns: id*, project_id*, project_title*, project_region*, created_at, updated_at (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `organization:user:add`
Invite a user to an organization
### Usage
```
upsun organization:user:add [-o|--org ORG] [--permission PERMISSION] [--] []
```
#### Arguments
* `email`(optional)
The email address of the user
#### Options
* `--org` (`-o`) (expects a value)
The organization name (or ID)
* `--permission` (expects a value)
Permission(s) for the user on the organization. Valid permissions are: billing, members, plans, projects:create, projects:list
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `organization:user:delete`
Remove a user from an organization
### Usage
```
upsun organization:user:delete [-o|--org ORG] [--]
```
#### Arguments
* `email`(required)
The email address of the user
#### Options
* `--org` (`-o`) (expects a value)
The organization name (or ID)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `organization:user:get`
View an organization user
### Usage
```
upsun organization:user:get [-o|--org ORG] [-P|--property PROPERTY] [--date-fmt DATE-FMT] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [--] []
```
#### Arguments
* `email`(optional)
The email address of the user
#### Options
* `--org` (`-o`) (expects a value)
The organization name (or ID)
* `--property` (`-P`) (expects a value)
A property to display
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `organization:user:list`
List organization users
Aliases: `org:users`
### Usage
```
upsun org:users [-c|--count COUNT] [--sort SORT] [--reverse] [-o|--org ORG] [--date-fmt DATE-FMT] [--format FORMAT] [--columns COLUMNS] [--no-header]
```
#### Options
* `--count` (`-c`) (expects a value)
The number of items to display per page. Use 0 to disable pagination.
* `--sort` (expects a value)
A property to sort by (created_at or updated_at)
* `--reverse`
Reverse the sort order
* `--org` (`-o`) (expects a value)
The organization name (or ID)
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (expects a value)
Columns to display. Available columns: id*, email*, owner*, permissions*, created_at, first_name, last_name, mfa_enabled, sso_enabled, updated_at, username (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `organization:user:projects`
List the projects a user can access
Aliases: `oups`
### Usage
```
upsun oups [-o|--org ORG] [--list-all] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [--date-fmt DATE-FMT] [--] []
```
#### Arguments
* `email`(optional)
The email address of the user
#### Options
* `--org` (`-o`) (expects a value)
The organization name (or ID)
* `--list-all`
List access across all organizations
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: project_id*, project_title*, roles*, updated_at*, granted_at, organization_id, organization_label, organization_name, region (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `organization:user:update`
Update an organization user
### Usage
```
upsun organization:user:update [-o|--org ORG] [--permission PERMISSION] [--] []
```
#### Arguments
* `email`(optional)
The email address of the user
#### Options
* `--org` (`-o`) (expects a value)
The organization name (or ID)
* `--permission` (expects a value)
Permission(s) for the user on the organization. Valid permissions are: billing, members, plans, projects:create, projects:list
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `project:clear-build-cache`
Clear a project's build cache
### Usage
```
upsun project:clear-build-cache [-p|--project PROJECT]
```
#### Options
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `project:create`
Create a new project
Aliases: `create`
### Usage
```
upsun create [-o|--org ORG] [--title TITLE] [--region REGION] [--plan PLAN] [--environments ENVIRONMENTS] [--storage STORAGE] [--default-branch DEFAULT-BRANCH] [--set-remote] [--no-set-remote]
```
Use this command to create a new project.
An interactive form will be presented with the available options. If the
command is run non-interactively (with --yes), the form will not be displayed,
and the --region option will be required.
A project subscription will be requested, and then checked periodically (every
3 seconds) until the project has been activated, or until the process times
out (15 minutes by default).
If known, the project ID will be output to STDOUT. All other output will be sent
to STDERR.
#### Options
* `--org` (`-o`) (expects a value)
The organization name (or ID)
* `--title` (expects a value)
The initial project title
* `--region` (expects a value)
The region where the project will be hosted. Get a 3% discount on resources for regions with a carbon intensity of less than 100 gCO2eq/kWh.
* `--plan` (expects a value)
The subscription plan
* `--environments` (expects a value)
The number of environments
* `--storage` (expects a value)
The amount of storage per environment, in GiB
* `--default-branch` (expects a value)
The default Git branch name for the project (the production environment)
* `--set-remote`
Set the new project as the remote for this repository. This is the default if no remote project is already set.
* `--no-set-remote`
Do not set the new project as the remote for this repository
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `project:delete`
Delete a project
### Usage
```
upsun project:delete [-p|--project PROJECT] [--] []
```
#### Arguments
* `project`(optional)
The project ID
#### Options
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `project:get`
Clone a project locally
Aliases: `get`
### Usage
```
upsun get [-e|--environment ENVIRONMENT] [--depth DEPTH] [-p|--project PROJECT] [--] [] []
```
#### Arguments
* `project`(optional)
The project ID
* `directory`(optional)
The directory to clone to. Defaults to the project title
#### Options
* `--environment` (`-e`) (expects a value)
The environment ID to clone. Defaults to the project default, or the first available environment
* `--depth` (expects a value)
Create a shallow clone: limit the number of commits in the history
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Clone the project "abc123" into the directory "my-project":
```
upsun project:get abc123 my-project
```
## `project:info`
Read or set properties for a project
### Usage
```
upsun project:info [--refresh] [--date-fmt DATE-FMT] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [-p|--project PROJECT] [-W|--no-wait] [--wait] [--] [] []
```
#### Arguments
* `property`(optional)
The name of the property
* `value`(optional)
Set a new value for the property
#### Options
* `--refresh`
Whether to refresh the cache
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Read all project properties:
```
upsun project:info
```
* Show the project's Git URL:
```
upsun project:info git
```
* Change the project's title:
```
upsun project:info title "My project"
```
## `project:init`
Initialize a project
Aliases: `ify`
### Usage
```
upsun project:init
```
#### Options
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|vv|vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Create the starter YAML files for your project:
```
upsun project:init
```
## `project:list`
Get a list of all active projects
Aliases: `projects`, `pro`
### Usage
```
upsun projects [--pipe] [--region REGION] [--title TITLE] [--my] [--refresh REFRESH] [--sort SORT] [--reverse] [--page PAGE] [-c|--count COUNT] [-o|--org ORG] [--format FORMAT] [--columns COLUMNS] [--no-header] [--date-fmt DATE-FMT]
```
#### Options
* `--pipe`
Output a simple list of project IDs. Disables pagination.
* `--region` (expects a value)
Filter by region (exact match)
* `--title` (expects a value)
Filter by title (case-insensitive search)
* `--my`
Display only the projects you own (through organizations you own)
* `--refresh` (expects a value)
Whether to refresh the list
* `--sort` (expects a value)
A property to sort by
* `--reverse`
Sort in reverse (descending) order
* `--page` (expects a value)
Page number. This enables pagination, despite configuration or --count. Ignored if --pipe is specified.
* `--count` (`-c`) (expects a value)
The number of projects to display per page. Use 0 to disable pagination. Ignored if --page is specified.
* `--org` (`-o`) (expects a value)
Filter by organization name or ID
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (expects a value)
Columns to display. Available columns: id*, title*, region*, organization_name*, created_at, organization_id, organization_label, status (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `project:set-remote`
Set the remote project for the current Git repository
Aliases: `set-remote`
### Usage
```
upsun set-remote []
```
#### Arguments
* `project`(optional)
The project ID
#### Options
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Set the remote project for this repository to "abcdef123456":
```
upsun project:set-remote abcdef123456
```
* Unset the remote project for this repository:
```
upsun project:set-remote -
```
## `repo:cat`
Read a file in the project repository
### Usage
```
upsun repo:cat [-c|--commit COMMIT] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--]
```
#### Arguments
* `path`(required)
The path to the file
#### Options
* `--commit` (`-c`) (expects a value)
The commit SHA. This can also accept "HEAD", and caret (^) or tilde (~) suffixes for parent commits.
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Read the configuration file:
```
upsun repo:cat .upsun/config.yaml
```
## `repo:ls`
List files in the project repository
### Usage
```
upsun repo:ls [-d|--directories] [-f|--files] [--git-style] [-c|--commit COMMIT] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--] []
```
#### Arguments
* `path`(optional)
The path to a subdirectory
#### Options
* `--directories` (`-d`)
Show directories only
* `--files` (`-f`)
Show files only
* `--git-style`
Style output similar to "git ls-tree"
* `--commit` (`-c`) (expects a value)
The commit SHA. This can also accept "HEAD", and caret (^) or tilde (~) suffixes for parent commits.
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `repo:read`
Read a directory or file in the project repository
Aliases: `read`
### Usage
```
upsun read [-c|--commit COMMIT] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--] []
```
#### Arguments
* `path`(optional)
The path to the directory or file
#### Options
* `--commit` (`-c`) (expects a value)
The commit SHA. This can also accept "HEAD", and caret (^) or tilde (~) suffixes for parent commits.
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `resources:build:get`
View the build resources of a project
Aliases: `build-resources:get`, `build-resources`
### Usage
```
upsun build-resources:get [-p|--project PROJECT] [--format FORMAT] [-c|--columns COLUMNS] [--no-header]
```
#### Options
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: cpu, memory. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `resources:build:set`
Set the build resources of a project
Aliases: `build-resources:set`
### Usage
```
upsun build-resources:set [--cpu CPU] [--memory MEMORY] [-p|--project PROJECT]
```
#### Options
* `--cpu` (expects a value)
Build CPU
* `--memory` (expects a value)
Build memory (in MB)
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `resources:get`
View the resources of apps and services on an environment
Aliases: `resources`, `res`
### Usage
```
upsun resources [-s|--service SERVICE] [--app APP] [--worker WORKER] [--type TYPE] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--format FORMAT] [-c|--columns COLUMNS] [--no-header]
```
#### Options
* `--service` (`-s`) (expects a value)
Filter by service name. This can select any service, including apps and workers.
* `--app` (expects a value)
Filter by app name
* `--worker` (expects a value)
Filter by worker name
* `--type` (expects a value)
Filter by service, app or worker type, e.g. "postgresql"
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: service*, profile_size*, cpu*, memory*, disk*, instance_count*, base_memory, memory_ratio, profile, type (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `resources:set`
Set the resources of apps and services on an environment
### Usage
```
upsun resources:set [-S|--size SIZE] [-C|--count COUNT] [-D|--disk DISK] [-f|--force] [--dry-run] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-W|--no-wait] [--wait]
```
Configure the resources allocated to apps, workers and services on an environment.
The resources may be the profile size, the instance count, or the disk size (MB).
Profile sizes are predefined CPU & memory values that can be viewed by running: upsun resources:sizes
If the same service and resource is specified on the command line multiple times, only the final value will be used.
#### Options
* `--size` (`-S`) (expects a value)
Set the profile size (CPU and memory) of apps, workers, or services. Items are in the format name:value and may be comma-separated. The % or * characters may be used as a wildcard for the name. List available sizes with the resources:sizes command. A value of 'default' will use the default size, and 'min' or 'minimum' will use the minimum.
* `--count` (`-C`) (expects a value)
Set the instance count of apps or workers. Items are in the format name:value as above.
* `--disk` (`-D`) (expects a value)
Set the disk size (in MB) of apps or services. Items are in the format name:value as above. A value of 'default' will use the default size, and 'min' or 'minimum' will use the minimum.
* `--force` (`-f`)
Try to run the update, even if it might exceed your limits
* `--dry-run`
Show the changes that would be made, without changing anything
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Set profile sizes for two apps and a service:
```
upsun resources:set --size frontend:0.1,backend:.25,database:1
```
* Give the "backend" app 3 instances:
```
upsun resources:set --count backend:3
```
* Give 512 MB disk to the "backend" app and 2 GB to the "database" service:
```
upsun resources:set --disk backend:512,database:2048
```
* Set the same profile size for the "backend" and "frontend" apps using a wildcard:
```
upsun resources:set --size '*end:0.1'
```
* Set the same instance count for all apps using a wildcard:
```
upsun resources:set --count '*:3'
```
## `resources:size:list`
List container profile sizes
Aliases: `resources:sizes`
### Usage
```
upsun resources:sizes [-s|--service SERVICE] [--profile PROFILE] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--format FORMAT] [-c|--columns COLUMNS] [--no-header]
```
#### Options
* `--service` (`-s`) (expects a value)
A service name
* `--profile` (expects a value)
A profile name
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: cpu, memory, size. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `route:get`
View detailed information about a route
### Usage
```
upsun route:get [--id ID] [-1|--primary] [-P|--property PROPERTY] [--refresh] [--date-fmt DATE-FMT] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP] [-i|--identity-file IDENTITY-FILE] [--] []
```
#### Arguments
* `route`(optional)
The route's original URL
#### Options
* `--id` (expects a value)
A route ID to select
* `--primary` (`-1`)
Select the primary route
* `--property` (`-P`) (expects a value)
The property to display
* `--refresh`
Bypass the cache of routes
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
[Deprecated option, no longer used]
* `--identity-file` (`-i`) (expects a value)
[Deprecated option, no longer used]
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* View the URL to the https://{default}/ route:
```
upsun route:get 'https://{default}/' -P url
```
## `route:list`
List all routes for an environment
Aliases: `routes`
### Usage
```
upsun routes [--refresh] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--] []
```
#### Arguments
* `environment`(optional)
The environment ID
#### Options
* `--refresh`
Bypass the cache of routes
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: route*, type*, to*, url (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `service:list`
List services in the project
Aliases: `services`
### Usage
```
upsun services [--refresh] [--pipe] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--format FORMAT] [-c|--columns COLUMNS] [--no-header]
```
#### Options
* `--refresh`
Whether to refresh the cache
* `--pipe`
Output a list of service names only
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: disk, name, size, type. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `service:mongo:dump`
Create a binary archive dump of data from MongoDB
Aliases: `mongodump`
### Usage
```
upsun mongodump [-c|--collection COLLECTION] [-z|--gzip] [-o|--stdout] [-r|--relationship RELATIONSHIP] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP]
```
#### Options
* `--collection` (`-c`) (expects a value)
The collection to dump
* `--gzip` (`-z`)
Compress the dump using gzip
* `--stdout` (`-o`)
Output to STDOUT instead of a file
* `--relationship` (`-r`) (expects a value)
The service relationship to use
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `service:mongo:export`
Export data from MongoDB
Aliases: `mongoexport`
### Usage
```
upsun mongoexport [-c|--collection COLLECTION] [--jsonArray] [--type TYPE] [-f|--fields FIELDS] [-r|--relationship RELATIONSHIP] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP]
```
#### Options
* `--collection` (`-c`) (expects a value)
The collection to export
* `--jsonArray`
Export data as a single JSON array
* `--type` (expects a value)
The export type, e.g. "csv"
* `--fields` (`-f`) (expects a value)
The fields to export
* `--relationship` (`-r`) (expects a value)
The service relationship to use
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Export a CSV from the "users" collection:
```
upsun service:mongo:export -c users --type csv -f name,email
```
## `service:mongo:restore`
Restore a binary archive dump of data into MongoDB
Aliases: `mongorestore`
### Usage
```
upsun mongorestore [-c|--collection COLLECTION] [-r|--relationship RELATIONSHIP] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP]
```
#### Options
* `--collection` (`-c`) (expects a value)
The collection to restore
* `--relationship` (`-r`) (expects a value)
The service relationship to use
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `service:mongo:shell`
Use the MongoDB shell
Aliases: `mongo`
### Usage
```
upsun mongo [--eval EVAL] [-r|--relationship RELATIONSHIP] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP]
```
#### Options
* `--eval` (expects a value)
Pass a JavaScript fragment to the shell
* `--relationship` (`-r`) (expects a value)
The service relationship to use
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Display collection names:
```
upsun service:mongo:shell --eval 'printjson(db.getCollectionNames())'
```
## `service:redis-cli`
Access the Redis CLI
Aliases: `redis`
### Usage
```
upsun redis [-r|--relationship RELATIONSHIP] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP] [--] []
```
#### Arguments
* `args`(optional)
Arguments to add to the Redis command
#### Options
* `--relationship` (`-r`) (expects a value)
The service relationship to use
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Open the redis-cli shell:
```
upsun service:redis-cli
```
* Ping the Redis server:
```
upsun service:redis-cli ping
```
* Show Redis status information:
```
upsun service:redis-cli info
```
* Scan keys:
```
upsun service:redis-cli -- --scan
```
* Scan keys matching a pattern:
```
upsun service:redis-cli -- "--scan --pattern '*-11*'"
```
## `source-operation:list`
List source operations on an environment
Aliases: `source-ops`
### Usage
```
upsun source-ops [--full] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--format FORMAT] [-c|--columns COLUMNS] [--no-header]
```
#### Options
* `--full`
Do not limit the length of command to display. The default limit is 24 lines.
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: app, command, operation. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `source-operation:run`
Run a source operation
### Usage
```
upsun source-operation:run [--variable VARIABLE] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-W|--no-wait] [--wait] [--] []
```
#### Arguments
* `operation`(optional)
The operation name
#### Options
* `--variable` (expects a value)
A variable to set during the operation, in the format type:name=value
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Run the "update" operation, setting environment variable FOO=bar:
```
upsun source-operation:run update --variable env:FOO=bar
```
## `ssh-cert:load`
Generate an SSH certificate
### Usage
```
upsun ssh-cert:load [--refresh-only] [--new] [--new-key]
```
This command checks if a valid SSH certificate is present, and generates a
new one if necessary.
Certificates allow you to make SSH connections without having previously
uploaded a public key. They are more secure than keys and they allow for
other features.
Normally the certificate is loaded automatically during login, or when
making an SSH connection. So this command is seldom needed.
If you want to set up certificates without login and without an SSH-related
command, for example if you are writing a script that uses an API token via
an environment variable, then you would probably want to run this command
explicitly. For unattended scripts, remember to turn off interaction via
--yes or the UPSUN_CLI_NO_INTERACTION environment variable.
#### Options
* `--refresh-only`
Only refresh the certificate, if necessary (do not write SSH config)
* `--new`
Force the certificate to be refreshed
* `--new-key`
Force a new key pair to be generated
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `ssh-key:add`
Add a new SSH key
### Usage
```
upsun ssh-key:add [--name NAME] [--] []
```
This command lets you add an SSH key to your account. It can generate a key using OpenSSH.
Notice:
SSH keys are no longer needed by default, as SSH certificates are supported.
Certificates offer more security than keys.
To load or check your SSH certificate, run: upsun ssh-cert:load
#### Arguments
* `path`(optional)
The path to an existing SSH public key
#### Options
* `--name` (expects a value)
A name to identify the key
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `ssh-key:delete`
Delete an SSH key
### Usage
```
upsun ssh-key:delete []
```
This command lets you delete SSH keys from your account.
Notice:
SSH keys are no longer needed by default, as SSH certificates are supported.
Certificates offer more security than keys.
To load or check your SSH certificate, run: upsun ssh-cert:load
#### Arguments
* `id`(optional)
The ID of the SSH key to delete
#### Options
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Delete the key 123:
```
upsun ssh-key:delete 123
```
## `ssh-key:list`
Get a list of SSH keys in your account
Aliases: `ssh-keys`
### Usage
```
upsun ssh-keys [--format FORMAT] [-c|--columns COLUMNS] [--no-header]
```
This command lets you list SSH keys in your account.
Notice:
SSH keys are no longer needed by default, as SSH certificates are supported.
Certificates offer more security than keys.
To load or check your SSH certificate, run: upsun ssh-cert:load
#### Options
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: id*, title*, path*, fingerprint (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `subscription:info`
Read or modify subscription properties
### Usage
```
upsun subscription:info [-s|--id ID] [--date-fmt DATE-FMT] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [-p|--project PROJECT] [--] [] []
```
#### Arguments
* `property`(optional)
The name of the property
* `value`(optional)
Set a new value for the property
#### Options
* `--id` (`-s`) (expects a value)
The subscription ID
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* View all subscription properties:
```
upsun subscription:info
```
* View the subscription status:
```
upsun subscription:info status
```
* View the storage limit (in MiB):
```
upsun subscription:info storage
```
## `team:create`
Create a new team
### Usage
```
upsun team:create [--label LABEL] [--no-check-unique] [-r|--role ROLE] [--output-id] [-o|--org ORG]
```
#### Options
* `--label` (expects a value)
The team label
* `--no-check-unique`
Do not error if another team exists with the same label in the organization
* `--role` (`-r`) (expects a value)
Set the team's project and environment type roles Values may be split by commas (e.g. "a,b,c") and/or whitespace. The % or * characters may be used as a wildcard.
* `--output-id`
Output the new team's ID to stdout (instead of displaying the team info)
* `--org` (`-o`) (expects a value)
The organization name (or ID)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `team:delete`
Delete a team
### Usage
```
upsun team:delete [-o|--org ORG] [-t|--team TEAM]
```
#### Options
* `--org` (`-o`) (expects a value)
The organization name (or ID)
* `--team` (`-t`) (expects a value)
The team ID
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `team:get`
View a team
### Usage
```
upsun team:get [-o|--org ORG] [-p|--project PROJECT] [-t|--team TEAM] [-P|--property PROPERTY] [--date-fmt DATE-FMT] [--format FORMAT] [-c|--columns COLUMNS] [--no-header]
```
#### Options
* `--org` (`-o`) (expects a value)
The organization name (or ID)
* `--project` (`-p`) (expects a value)
The project ID or URL, to auto-select the organization if --org is not used
* `--team` (`-t`) (expects a value)
The team ID
* `--property` (`-P`) (expects a value)
The name of a property to view
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `team:list`
List teams
Aliases: `teams`
### Usage
```
upsun teams [-c|--count COUNT] [--sort SORT] [--reverse] [-o|--org ORG] [-p|--project PROJECT] [--date-fmt DATE-FMT] [--format FORMAT] [--columns COLUMNS] [--no-header]
```
#### Options
* `--count` (`-c`) (expects a value)
The number of items to display per page. Use 0 to disable pagination.
* `--sort` (expects a value)
A team property to sort by
* `--reverse`
Sort in reverse order
* `--org` (`-o`) (expects a value)
The organization name (or ID)
* `--project` (`-p`) (expects a value)
The project ID or URL, to auto-select the organization if --org is not used
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (expects a value)
Columns to display. Available columns: id*, label*, member_count*, project_count*, project_permissions*, created_at, updated_at (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `team:project:add`
Add project(s) to a team
### Usage
```
upsun team:project:add [--all] [-o|--org ORG] [-t|--team TEAM] [--] []...
```
#### Arguments
* `projects`(optional; multiple values allowed)
The project ID(s). Values may be split by commas (e.g. "a,b,c") and/or whitespace.
#### Options
* `--all`
Add all the projects that currently exist in the organization
* `--org` (`-o`) (expects a value)
The organization name (or ID)
* `--team` (`-t`) (expects a value)
The team ID
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `team:project:delete`
Remove a project from a team
### Usage
```
upsun team:project:delete [-o|--org ORG] [-t|--team TEAM] [--] []
```
#### Arguments
* `project`(optional)
The project ID
#### Options
* `--org` (`-o`) (expects a value)
The organization name (or ID)
* `--team` (`-t`) (expects a value)
The team ID
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `team:project:list`
List projects in a team
Aliases: `team:projects`, `team:pro`
### Usage
```
upsun team:projects [-c|--count COUNT] [-o|--org ORG] [-t|--team TEAM] [--date-fmt DATE-FMT] [--format FORMAT] [--columns COLUMNS] [--no-header]
```
#### Options
* `--count` (`-c`) (expects a value)
The number of items to display per page (max: 200). Use 0 to disable pagination
* `--org` (`-o`) (expects a value)
The organization name (or ID)
* `--team` (`-t`) (expects a value)
The team ID
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (expects a value)
Columns to display. Available columns: id*, title*, granted_at*, updated_at (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `team:update`
Update a team
### Usage
```
upsun team:update [--label LABEL] [--no-check-unique] [-r|--role ROLE] [-t|--team TEAM] [-o|--org ORG] [-W|--no-wait] [--wait]
```
#### Options
* `--label` (expects a value)
Set a new team label
* `--no-check-unique`
Do not error if another team exists with the same label in the organization
* `--role` (`-r`) (expects a value)
Set the team's project and environment type roles Values may be split by commas (e.g. "a,b,c") and/or whitespace. The % or * characters may be used as a wildcard.
* `--team` (`-t`) (expects a value)
The team ID
* `--org` (`-o`) (expects a value)
The organization name (or ID)
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `team:user:add`
Add a user to a team
### Usage
```
upsun team:user:add [-o|--org ORG] [-t|--team TEAM] [--] []
```
#### Arguments
* `user`(optional)
The user email address or ID
#### Options
* `--org` (`-o`) (expects a value)
The organization name (or ID)
* `--team` (`-t`) (expects a value)
The team ID
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `team:user:delete`
Remove a user from a team
### Usage
```
upsun team:user:delete [-o|--org ORG] [-t|--team TEAM] [--] []
```
#### Arguments
* `user`(optional)
The user email address or ID
#### Options
* `--org` (`-o`) (expects a value)
The organization name (or ID)
* `--team` (`-t`) (expects a value)
The team ID
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `team:user:list`
List users in a team
Aliases: `team:users`
### Usage
```
upsun team:users [-c|--count COUNT] [-o|--org ORG] [-t|--team TEAM] [--date-fmt DATE-FMT] [--format FORMAT] [--columns COLUMNS] [--no-header]
```
#### Options
* `--count` (`-c`) (expects a value)
The number of items to display per page. Use 0 to disable pagination
* `--org` (`-o`) (expects a value)
The organization name (or ID)
* `--team` (`-t`) (expects a value)
The team ID
* `--date-fmt` (expects a value)
The date format (as a PHP date format string)
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (expects a value)
Columns to display. Available columns: id*, email*, created_at*, updated_at (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `tunnel:close`
Close SSH tunnels
### Usage
```
upsun tunnel:close [-a|--all] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP]
```
#### Options
* `--all` (`-a`)
Close all tunnels
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `tunnel:info`
View relationship info for SSH tunnels
### Usage
```
upsun tunnel:info [-P|--property PROPERTY] [-c|--encode] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP]
```
#### Options
* `--property` (`-P`) (expects a value)
The relationship property to view
* `--encode` (`-c`)
Output as base64-encoded JSON
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `tunnel:list`
List SSH tunnels
Aliases: `tunnels`
### Usage
```
upsun tunnels [-a|--all] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP] [--format FORMAT] [-c|--columns COLUMNS] [--no-header]
```
#### Options
* `--all` (`-a`)
View all tunnels
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: port*, project*, environment*, app*, relationship*, url (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `tunnel:open`
Open SSH tunnels to an app's relationships
### Usage
```
upsun tunnel:open [-g|--gateway-ports] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP]
```
This command opens SSH tunnels to all of the relationships of an application.
Connections can then be made to the application's services as if they were
local, for example a local MySQL client can be used, or the Solr web
administration endpoint can be accessed through a local browser.
This command requires the posix and pcntl PHP extensions (as multiple
background CLI processes are created to keep the SSH tunnels open). The
tunnel:single command can be used on systems without these
extensions.
#### Options
* `--gateway-ports` (`-g`)
Allow remote hosts to connect to local forwarded ports
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `tunnel:single`
Open a single SSH tunnel to an app relationship
### Usage
```
upsun tunnel:single [--port PORT] [-g|--gateway-ports] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-A|--app APP] [-r|--relationship RELATIONSHIP]
```
#### Options
* `--port` (expects a value)
The local port
* `--gateway-ports` (`-g`)
Allow remote hosts to connect to local forwarded ports
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--app` (`-A`) (expects a value)
The remote application name
* `--relationship` (`-r`) (expects a value)
The service relationship to use
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `user:add`
Add a user to the project
### Usage
```
upsun user:add [-r|--role ROLE] [--force-invite] [-p|--project PROJECT] [-W|--no-wait] [--wait] [--] []
```
#### Arguments
* `email`(optional)
The user's email address
#### Options
* `--role` (`-r`) (expects a value)
The user's project role ('admin' or 'viewer') or environment type role (e.g. 'staging:contributor' or 'production:viewer'). To remove a user from an environment type, set the role as 'none'. The % or * characters can be used as a wildcard for the environment type, e.g. '%:viewer' to give the user the 'viewer' role on all types. The role can be abbreviated, e.g. 'production:v'.
* `--force-invite`
Send an invitation, even if one has already been sent
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Add Alice as a project admin:
```
upsun user:add alice@example.com -r admin
```
* Add Bob as a viewer on the "production" environment type, and a contributor on "development" environments:
```
upsun user:add bob@example.com -r production:v -r development:c
```
* Add Charlie as viewer on "production" and "development":
```
upsun user:add charlie@example.com -r prod%:v -r dev%:v
```
## `user:delete`
Delete a user from the project
### Usage
```
upsun user:delete [-p|--project PROJECT] [-W|--no-wait] [--wait] [--]
```
#### Arguments
* `email`(required)
The user's email address
#### Options
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Delete Alice from the project:
```
upsun user:delete alice@example.com
```
## `user:get`
View a user's role(s)
### Usage
```
upsun user:get [-l|--level LEVEL] [--pipe] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-W|--no-wait] [--wait] [-r|--role ROLE] [--] []
```
#### Arguments
* `email`(optional)
The user's email address
#### Options
* `--level` (`-l`) (expects a value)
The role level ('project' or 'environment')
* `--pipe`
Output the role to stdout (after making any changes)
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--role` (`-r`) (expects a value)
[Deprecated: use user:update to change a user's role(s)]
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* View Alice's role on the project:
```
upsun user:get alice@example.com
```
* View Alice's role on the current environment:
```
upsun user:get alice@example.com --level environment --pipe
```
## `user:list`
List project users
Aliases: `users`
### Usage
```
upsun users [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [-p|--project PROJECT]
```
#### Options
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: email*, name*, role*, id*, granted_at, permissions, updated_at (* = default columns). The character "+" can be used as a placeholder for the default columns. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `user:update`
Update user role(s) on a project
### Usage
```
upsun user:update [-r|--role ROLE] [-p|--project PROJECT] [-W|--no-wait] [--wait] [--] []
```
#### Arguments
* `email`(optional)
The user's email address
#### Options
* `--role` (`-r`) (expects a value)
The user's project role ('admin' or 'viewer') or environment type role (e.g. 'staging:contributor' or 'production:viewer'). To remove a user from an environment type, set the role as 'none'. The % or * characters can be used as a wildcard for the environment type, e.g. '%:viewer' to give the user the 'viewer' role on all types. The role can be abbreviated, e.g. 'production:v'.
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Make Bob an admin on the "development" and "staging" environment types:
```
upsun user:update bob@example.com -r development:a,staging:a
```
* Make Charlie a contributor on all environment types:
```
upsun user:update charlie@example.com -r %:c
```
## `variable:create`
Create a variable
### Usage
```
upsun variable:create [-u|--update] [-l|--level LEVEL] [--name NAME] [--value VALUE] [--json JSON] [--sensitive SENSITIVE] [--prefix PREFIX] [--enabled ENABLED] [--inheritable INHERITABLE] [--visible-build VISIBLE-BUILD] [--visible-runtime VISIBLE-RUNTIME] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-W|--no-wait] [--wait] [--] []
```
#### Arguments
* `name`(optional)
The variable name
#### Options
* `--update` (`-u`)
Update the variable if it already exists
* `--level` (`-l`) (expects a value)
The level at which to set the variable ('project' or 'environment')
* `--name` (expects a value)
The variable name
* `--value` (expects a value)
The variable's value
* `--json` (expects a value)
Whether the variable value is JSON-formatted
* `--sensitive` (expects a value)
Whether the variable value is sensitive
* `--prefix` (expects a value)
The variable name's prefix which can determine its type, e.g. 'env'. Only applicable if the name does not already contain a prefix. (e.g. 'none' or 'env:')
* `--enabled` (expects a value)
Whether the variable should be enabled on the environment
* `--inheritable` (expects a value)
Whether the variable is inheritable by child environments
* `--visible-build` (expects a value)
Whether the variable should be visible at build time
* `--visible-runtime` (expects a value)
Whether the variable should be visible at runtime
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `variable:delete`
Delete a variable
### Usage
```
upsun variable:delete [-l|--level LEVEL] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-W|--no-wait] [--wait] [--]
```
#### Arguments
* `name`(required)
The variable name
#### Options
* `--level` (`-l`) (expects a value)
The variable level ('project', 'environment', 'p' or 'e')
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* Delete the variable "example":
```
upsun variable:delete example
```
## `variable:get`
View a variable
Aliases: `vget`
### Usage
```
upsun vget [-P|--property PROPERTY] [-l|--level LEVEL] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--pipe] [--] []
```
#### Arguments
* `name`(optional)
The name of the variable
#### Options
* `--property` (`-P`) (expects a value)
View a single variable property
* `--level` (`-l`) (expects a value)
The variable level ('project', 'environment', 'p' or 'e')
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--pipe`
[Deprecated option] Output the variable value only
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
### Examples
* View the variable "example":
```
upsun variable:get example
```
## `variable:list`
List variables
Aliases: `variables`, `var`
### Usage
```
upsun variables [-l|--level LEVEL] [--format FORMAT] [-c|--columns COLUMNS] [--no-header] [-p|--project PROJECT] [-e|--environment ENVIRONMENT]
```
#### Options
* `--level` (`-l`) (expects a value)
The variable level ('project', 'environment', 'p' or 'e')
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: is_enabled, level, name, value. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `variable:update`
Update a variable
### Usage
```
upsun variable:update [--allow-no-change] [-l|--level LEVEL] [--value VALUE] [--json JSON] [--sensitive SENSITIVE] [--enabled ENABLED] [--inheritable INHERITABLE] [--visible-build VISIBLE-BUILD] [--visible-runtime VISIBLE-RUNTIME] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [-W|--no-wait] [--wait] [--]
```
#### Arguments
* `name`(required)
The variable name
#### Options
* `--allow-no-change`
Return success (zero exit code) if no changes were provided
* `--level` (`-l`) (expects a value)
The variable level ('project', 'environment', 'p' or 'e')
* `--value` (expects a value)
The variable's value
* `--json` (expects a value)
Whether the variable value is JSON-formatted
* `--sensitive` (expects a value)
Whether the variable value is sensitive
* `--enabled` (expects a value)
Whether the variable should be enabled on the environment
* `--inheritable` (expects a value)
Whether the variable is inheritable by child environments
* `--visible-build` (expects a value)
Whether the variable should be visible at build time
* `--visible-runtime` (expects a value)
Whether the variable should be visible at runtime
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--no-wait` (`-W`)
Do not wait for the operation to complete
* `--wait`
Wait for the operation to complete (default)
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
## `worker:list`
Get a list of all deployed workers
Aliases: `workers`
### Usage
```
upsun workers [--refresh] [--pipe] [-p|--project PROJECT] [-e|--environment ENVIRONMENT] [--format FORMAT] [-c|--columns COLUMNS] [--no-header]
```
#### Options
* `--refresh`
Whether to refresh the cache
* `--pipe`
Output a list of worker names only
* `--project` (`-p`) (expects a value)
The project ID or URL
* `--environment` (`-e`) (expects a value)
The environment ID. Use "." to select the project's default environment.
* `--format` (expects a value)
The output format: table, csv, tsv, or plain
* `--columns` (`-c`) (expects a value)
Columns to display. Available columns: commands, name, type. The % or * characters may be used as a wildcard. Values may be split by commas (e.g. "a,b,c") and/or whitespace.
* `--no-header`
Do not output the table header
* `--help` (`-h`)
Display this help message
* `--verbose` (`-v|-vv|-vvv`)
Increase the verbosity of messages
* `--version` (`-V`)
Display this application version
* `--yes` (`-y`)
Answer "yes" to confirmation questions; accept the default value for other questions; disable interaction
* `--no-interaction`
Do not ask any interactive questions; accept default values. Equivalent to using the environment variable: UPSUN_CLI_NO_INTERACTION=1
# Set up a custom domain [Configure a third-party TLS certificate](https://docs.upsun.com/domains/steps/tls.html)
Upsun automatically provides standard Transport Layer Security (TLS) certificates for all sites and environments.
These certificates are issued at no charge by [Let's Encrypt](https://letsencrypt.org/) and cover most needs.
To use them, you need to [specify HTTPS routes](../../define-routes/https.md#enable-https).
Note that some [limitations](../../define-routes/https.md#lets-encrypt-limitations) apply.
Upsun allows you to use third-party TLS certificates free of charge.
You can use many kinds of custom certificates, including domain-validated, extended validation, high-assurance, or wildcard certificates.
Consult your TLS issuer for pricing and instructions on how to generate a TLS certificate.
Seven days before a third-party custom certificate is due to expire,
Upsun replaces it with a new default Let’s Encrypt certificate.
This helps prevent downtime.
To avoid switching to a default certificate,
make sure you replace your custom certificate with an updated one
more than seven days before its expiration date.
Note that custom certificates aren't necessary for preview environments.
Wildcard certificates that cover all `*.platform.sh` domains, including preview environments, are automatically provided.
### Add a custom certificate
You can add a custom certificate using the [CLI](../../administration/cli/_index.md) or in the [Console](../../administration/web/_index.md).
Your certificate has to be in PKCS #1 format and start with `-----BEGIN RSA PRIVATE KEY-----`.
If it doesn't start that way, [change the format](#change-the-private-key-format).
To add your custom certificate, follow these steps:
You can optionally include intermediate SSL certificates by adding ‐‐chain PATH_TO_FILE for each one.
Redeploy your production environment with the following command:
upsun environment:redeploy
Open the project where you want to add a certificate.
Click Settings.
Click Certificates.
Click + Add.
Fill in your private key, public key certificate, and (optionally) intermediate SSL certificates.
Click Add Certificate.
Access your production environment.
Click More.
Click Redeploy.
### Change the private key format
The expected format for your certificate’s private key is PKCS #1.
Private keys in PKCS #1 format start with `-----BEGIN RSA PRIVATE KEY-----`.
If your private key starts with `-----BEGIN PRIVATE KEY-----`, it’s in PKCS #8 format, which isn’t appropriate.
To convert your private key (`private.key`) from PKCS #8 to PKCS #1 format (`private.rsa.key`), run the following command:
```bash
openTLS rsa -in private.key -out private.rsa.key
```
# Best practices [From monoliths through headless to microservices](https://docs.upsun.com/learn/bestpractices/oneormany.html)
With Upsun, you can run multiple application containers in a single environment.
This gives you access to a large variety of setups and allows you to seamlessly upgrade your app
from a monolith with a single application server to a more elaborate and effective topology.
You can set up multiple apps to achieve the following:
- Keep your backend and frontend systems separate
- Run workers alongside your main app
- Or even go for a full microservices architecture
Upsun makes implementing such setups and switching from one to the other pain-free.
The same flexibility applies to any supported services, from relational databases to search engines and message queues.
Depending on your specific use case, you can run a single database,
multiple databases inside a single instance, or multiple databases in multiple versions...
It's up to you!
Whether you embrace a mono-repo approach with a single Git repository describing your entire setup,
or divide your project into multiple repositories, Upsun allows you to build the best architecture for your needs.
But while the possibilities are endless, making the right choice between creating one big project with multiple apps
or keeping each app in its own project can be a tough formula to crack.
So read on for guidance!
## Separate projects
If you have multiple apps sharing the same code but each of them has its own data,
keep your apps in separate projects.
Upsun provides the automation to deploy multiple projects from the same code base,
which makes their maintenance effortless.
Note
By design, Upsun doesn’t allow your app to access services in another project through HTTP.
So separate projects are appropriate in the following cases:
- Your apps are for different customers/clients
- Your apps don't need to directly connect to the same database
- Different teams are working on different apps
- You want to develop true microservices, where each microservice is a fully standalone process with its own data
When in doubt over your own needs,
it's better to keep separate projects than build an architecture that may prove difficult for you to maintain.
## Clustered applications
A clustered application is one where your project requires multiple _app services_ that are all part of the same conceptual project.
Clustered applications can range from a straightforward headless architecture, where frontend and backend systems are separated,
to micro-services with dozens of apps in multiple runtimes and frameworks forming a consistent whole.
Meaning, removing one of the app services would break the others.
Upsun allows you to configure access from one service to another
without having to worry about service discovery or complex _ingress controllers_.
[Configuring incoming routes](/define-routes/_index.md) is straightforward.
You can have services that are only exposed to another service as well as services that are exposed to the internet.
In a clustered application, you can have one of the following configurations:
- Multiple [applications](/create-apps/multi-app/_index.md), often in different directories or with separate code bases that deploy separately
- A single app that spawns one or more [worker instances](/create-apps/app-reference/single-runtime-image.md#workers) that run background processes
With a clustered application, you often don't need multiple service instances.
The [MySQL, MariaDB](/add-services/mysql/_index.md),
and [Solr](/add-services/solr.md) services support defining multiple databases on a single service,
which is significantly more efficient than defining multiple services.
[Redis](/add-services/redis.md), [Memcached](/add-services/memcached.md),
[Elasticsearch](/add-services/elasticsearch.md), and [RabbitMQ](/add-services/rabbitmq.md)
natively support multiple bins (also called _queues_ or _indexes_) defined by the client application as part of the request.
Therefore, they don't need additional configuration on Upsun.
Clustered applications are appropriate in the following cases:
- You want one user-facing app and an entirely separate admin-facing app that are both operating on the same data
- You want to have a user-facing app and a separate worker process (either the same code or separate) that handles background tasks
- You want a single conceptual app written in multiple programming languages
## A note on "multi-site" applications
Some Content Management Systems or other applications support running multiple logical "sites" off of a single code base.
This approach isn't recommended on Upsun.
This multi-site logic is often dependent on the domain name of the incoming request, which on Upsun varies by branch.
Running multiple databases, as is often recommended with this approach,
is supported on Upsun but makes the setup process for each site more difficult.
Leveraging the multi-site capabilities of an app are appropriate only in the following cases:
- There is only a single team working on all of the "sites" involved
- All "sites" should be updated simultaneously as a single unit
- Each individual site is relatively low traffic, such that the aggregate traffic is appropriate for your plan size
- All sites really do use the same codebase with no variation, just different data
Otherwise, [separate projects](#separate-projects) are a better long-term plan.
# Set up a custom domain [Handle subdomains across different projects](https://docs.upsun.com/domains/steps/subdomains.html)
You can host multiple subdomains, such as `foo.example.com` and `bar.example.com`,
within a single project using [routes](../../define-routes/_index.md).
If you try to use a subdomain that's used in another project,
you get an error like the following:
```text
This domain is already claimed by another service
```
You need to add a DNS record to make it clear you explicitly allow multiple projects to use the domain.
## Enable subdomains across multiple projects
To ensure multiple projects can use subdomains of the same apex domain,
add a specific `TXT` DNS record for your apex domain.
The `TXT` record should look like the following:
```text
_public-suffix-root.YOUR_APEX_DOMAIN TXT "public-suffix-root=YOUR_APEX_DOMAIN"
```
This adds your domain to the [Upsun implementation of the Public Suffix List](#why-this-is-necessary).
After you add your subdomains, remove the `TXT` record to reinstate [subdomain hijacking protection](#subdomain-hijacking-protection).
This ensures no other users can possibly add a subdomain of your domain to their project.
Even if you don’t remove the record, your DNS records should prevent others from using a subdomain
as long as you don’t use wildcards records pointing at Upsun.
However, if you don't remove the `TXT` record, restrictions apply on the apex domain.
For example, you can't add the apex domain to another project until you remove the `TXT` record.
## Bypass locked domains
In certain cases (such as if your domain was added manually by Upsun support),
your domain may be reserved for the project you added it to.
Then you can't set up a second project with the bare domain (`example.com`) or a subdomain (`foo.example.com`).
If that happens, [contact support](/learn/overview/get-support.md).
Include the project ID of the project that already has the domain.
## Why this is necessary
### The Public Suffix List
Domain names are segmented into different hierarchical levels, separated by a `.`.
The right-most portion of the domain, such as `.com`, `.edu`, and `.fr`,
is known as the top-level domain (TLD).
Most applications, including web browsers, handle TLDs specially, such as by restricting certain actions.
For example, a webpage at `foo.bar.baz.example.com` can usually set a cookie that's keyed to any of the following:
- `foo.bar.baz.example.com`
- `bar.baz.example.com`
- `baz.example.com`
- `example.com`
So a single site can be segmented across different subdomains but use a single account login cookie.
But this webpage *can't* set cookies keyed to all `.com` domains,
which would be a security risk.
Other restrictions apply to TLDs, but cookies are the most basic example.
Aside from true TLDs, browser makers have a list of domain suffixes that should get the same special handling
called the [Public Suffix List (PSL)](https://publicsuffix.org/).
If you add the `example.com` domain to the PSL,
browsers refuse to set a cookie on `example.com` from a page at `foo.example.com`.
They still accept cookies from a page at `example.com`.
### Subdomain hijacking protection
By default, a given domain can be used by only one project at a time.
This security measure prevents malicious actions such as registering a project with the `evil.example.com` subdomain
and using that to set cookies on your `example.com` website.
When you add a domain to a project,
the first level of the domain not in the [PSL](#the-public-suffix-list) is reserved.
So if you add `foo.bar.baz.example.com` to a project,
that project has `example.com` reserved within Upsun
and no other project can have a domain anywhere in `*.example.com`.
You can add multiple subdomains within that one project.
Subdomain hijacking protection ensures that no other users can add a subdomain to their project
as long as you don't use wildcard DNS records pointing at Upsun.
In most cases, that's a desirable added layer of security.
But you may run into a problem when you want multiple subdomains from the same organization as separate projects.
One option would be to add `example.com` to the PSL, but you might not want or be able to do that.
To limit what domains get protected, Upsun supports a small extension to the PSL.
When you add a `TXT` record for your domain, Upsun treats that domain as part of the PSL.
So when you add a `TXT` record for `example.com`,
Upsun treats `example.com` as a top-level domain.
That means it isn't reserved and is open for other projects.
Then when you add a domain, the next level down from `example.com` is reserved.
So if you add `foo.bar.baz.example.com` to a project, `*.baz.example.com` is reserved for that project.
You can add `beep.example.com` to a different project without any issues.
You can do the same for any level of subdomain.
So if you set a `TXT` record for `baz.example.com`
and add `foo.bar.baz.example.com` to a project,
`*.bar.baz.example.com` is reserved for that project.
Nothing at a higher level is reserved.
# Define routes [HTTP cache](https://docs.upsun.com/define-routes/cache.html)
Upsun supports HTTP caching at the server level. Caching is enabled by default, but is only applied to GET and HEAD requests.
The cache can be controlled using the `cache` key in your `.upsun/config.yaml` file.
If a request can be cached, Upsun builds a cache key from several request properties and stores the response associated with this key.
When a request comes with the same cache key, the cached response is reused.
When caching is on...
* you can configure cache behavior for different location blocks in your `.upsun/config.yaml`;
* the router respects whatever cache headers are sent by the application;
* cookies bypass the cache;
* responses with the `Cache-Control` header set to `Private`, `No-Cache`, or `No-Store` aren't cached.
You should _not_ use the Upsun HTTP cache if you're using [Varnish](../add-services/varnish.md) or an external CDN
such as [Fastly](../domains/cdn/fastly.md) or [Cloudflare](../domains/cdn/cloudflare.md).
Mixing cache services together most likely results in caches that are stale and can't be cleared.
For more details, see [best practices on HTTP caching](/learn/bestpractices/http-caching.md).
## Basic usage
The HTTP cache is enabled by default, however you may wish to override this behavior.
To configure the HTTP cache, add a `cache` key to your route. You may like to start with the defaults:
```yaml {configFile="routes"}
routes:
https://{default}/:
type: upstream
upstream: myapp:http
cache:
enabled: true
default_ttl: 0
cookies: ['*']
headers: ['Accept', 'Accept-Language']
```
## Example
In this example, requests are cached based on the URI, the `Accept` header, `Accept-Language` header, and `X-Language-Locale` header.
Any response that lacks a `Cache-Control` header is cached for 60 seconds.
The presence of any cookie in the request disables caching of that response.
```yaml {configFile="routes"}
routes:
https://{default}/:
type: upstream
upstream: myapp:http
cache:
enabled: true
headers: ['Accept', 'Accept-Language', 'X-Language-Locale']
cookies: ['*']
default_ttl: 60
```
## How it works
### The cache key
If a request can be cached, Upsun builds a cache key from several request properties and stores the response associated with this key. When a request comes with the same cache key, the cached response is reused.
There are two parameters that let you control this key: `headers` and `cookies`.
The default value for these keys are the following:
```yaml {configFile="routes"}
routes:
https://{default}/:
# ...
cache:
enabled: true
cookies: ['*']
headers: ['Accept', 'Accept-Language']
```
### Duration
The cache duration is decided based on the `Cache-Control` response header value. If no `Cache-Control` header is in the response, then the value of `default_ttl` key is used.
### Conditional requests
Conditional requests using `If-Modified-Since` and `If-None-Match` are both supported. The web server doesn't honor the `Pragma` request header.
### Cache revalidation
When the cache is expired (indicated by `Last-Modified` header in the response) the web server sends a request to your application with `If-Modified-Since` header.
If the `If-None-Match` header is sent in the conditional request when `Etag` header is set in the cached response, your application can extend the validity of the cache by replying `HTTP 304 Not Modified`.
### Flushing
The HTTP cache doesn't support a complete cache flush, but you can invalidate the cache by setting `cache: false`. Alternatively, the cache clears on a rebuild, so triggering a rebuild (pushing a new commit) effectively causes a complete cache flush.
## Cache configuration properties
### `enabled`
Turns the cache on or off for a route.
Type: Boolean
Required: Yes
Values
true: enable the cache for this route [default, but only if the cache key isn’t actually specified]
false: disable the cache for this route
### `headers`
Adds specific header fields to the cache key, enabling caching of separate responses for those headers.
For example, if the `headers` key is the following, Upsun caches a different response for each value of the `Accept` HTTP request header only:
```yaml {configFile="routes"}
routes:
https://{default}/:
# ...
cache:
enabled: true
headers: ["Accept"]
```
Type: List
Values:
['Accept', 'Accept-Language']: Cache on Accept & Accept-Language [default]
#### Header behaviors
The cache is only applied to `GET` and `HEAD` requests. Some headers trigger specific behaviors in the cache.
Header field | Cache behavior
-------------|----------------
`Cache-Control`|Responses with the `Cache-Control` header set to `Private`, `No-Cache`, or `No-Store` aren't cached. All other values override `default_ttl`.
`Vary`|A list of header fields to be taken into account when constructing the cache key. Multiple header fields can be listed, separated by commas. The Cache key is the union of the values of the Header fields listed in Vary header, and whatever is listed in the `.upsun/config.yaml` file.
`Set-Cookie`|Not cached
`Accept-Encoding`, `Connection`, `Proxy-Authorization`, `TE`, `Upgrade`|Not allowed, and throws an error
`Cookie`|Not allowed, and throws an error. Use the `cookies` value, instead.
`Pragma`|Ignored
A full list of HTTP headers is available on [Wikipedia](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields).
### `cookies`
The `cookies` key allows you to define a list of cookies you want to include in the cache key, if any.
| Possible values | Description | Default |
|--------------------------|---------------------------------------------------------------------------------------|---------|
| `['*']` | Any request with a cookie bypasses the cache. Note that this is achieved by Upsun adding the `X-Platform-Cache: BYPASS` HTTP header in the router, and that the same behaviour applies if the `Set-Cookie` header is present. | Yes |
| `[]` | Ignore all cookies. | No |
|`['cookie_1','cookie_2']` | A list of allowed cookies to include in the cache key. All other cookies are ignored. | No |
#### Example with a single value
With the following configuration, the cache key depends on the value of the `foo` cookie in the request.
Other cookies are ignored.
```yaml {configFile="routes"}
routes:
https://{default}/:
# ...
cache:
enabled: true
cookies: ["foo"]
```
#### Example with a regular expression
A cookie value can also be a regular expression.
An entry that begins and ends with a `/` is interpreted as a PCRE regular expression to match the cookie name.
For example:
```yaml {configFile="routes"}
routes:
https://{default}/:
# ...
cache:
enabled: true
cookies: ['/^SS?ESS/']
```
This configuration causes all cookies beginning with `SESS` or `SSESS` to be part of the cache key, as a single value.
Other cookies are ignored for caching.
If your site uses a session cookie as well as third-party cookies, say from an analytics service,
this is the recommended approach.
### `default_ttl`
Defines the default time-to-live for the cache, in seconds, for non-static responses, when the response doesn't specify one.
The cache duration is decided based on the `Cache-Control` response header value. If no `Cache-Control` header is in the response, then the value of `default_ttl` is used. If the application code returns a `Cache-Control` header or if your `.upsun/config.yaml` file is configured to set a cache lifetime, then this value is ignored in favor of the application headers.
The `default_ttl` only applies to **non-static responses**, that is, those generated by your application.
To set a cache lifetime for static resources configure that in your [app configuration](/create-apps/app-reference/single-runtime-image.md#locations).
All static assets have a Cache-Control header with a max age defaulting to 0 (which is the default for `expires`).
Type: integer
Values:
0: Do not cache [default]. This prevents caching, unless the response specifies a Cache-Control header value.
## Debugging
Upsun adds an `X-Platform-Cache` header to each request which show whether your request is a cache `HIT`, `MISS` or `BYPASS`. This can be useful when trying to determine whether it's your application, the HTTP cache, or another proxy or CDN which isn't behaving as expected.
If in doubt, disable the cache using `cache: false`.
## Advanced caching strategies
### Cache per route
If you need fine-grained caching, you can set up caching rules for several routes separately:
```yaml {configFile="routes"}
routes:
https://{default}/:
type: upstream
upstream: myapp:http
cache:
enabled: true
https://{default}/foo/:
type: upstream
upstream: myapp:http
cache:
enabled: false
https://{default}/foo/bar/:
type: upstream
upstream: myapp:http
cache:
enabled: true
```
With this configuration, the following routes are cached:
- `https://{default}/`
- `https://{default}/foo/bar/`
- `https://{default}/foo/bar/baz/`
And the following routes are **not** cached:
- `https://{default}/foo/`
- `https://{default}/foo/baz/`
Note
Regular expressions in routes are not supported.
### Allowing only specific cookies
Some applications use cookies to invalidate cache responses, but expect other cookies to be ignored.
This is a case of allowing only a subset of cookies to invalidate the cache.
```yaml {configFile="routes"}
routes:
https://{default}/:
# ...
cache:
enabled: true
cookies: ["MYCOOKIE"]
```
### Cache HTTP and HTTPS separately using the `Vary` header
Set the Vary header to `X-Forwarded-Proto` [custom request header](/development/headers.md) to render content based on the request protocol (i.e. HTTP or HTTPS). By adding `Vary: X-Forwarded-Proto` to the response header, HTTP and HTTPS content would be cached separately.
### Cache zipped content separately
Use `Vary: Accept-Encoding` to serve different content depending on the encoding. Useful for ensuring that gzipped content isn't served to clients that can't read it.
# Billing [Monitor your billing information](https://docs.upsun.com/administration/billing/monitor-billing.html)
To help you manage costs related to your organization,
Upsun provides estimates for the current month and the next.
You can set billing alerts to ensure you don't overspend,
and track resource usage on each of your projects.
For details on costs, see the [Upsun pricing page](https://upsun.com/pricing/).
## Access your organization billing information
To access your organization billing information in the [Console](/administration/web/_index.md):
1. Navigate to your organization.
2. Open the user menu (your name or profile picture).
3. Click **Billing**.
The **Overview** tab is displayed.
You can view your current month and next month estimates.

### Current month estimate
The [**Overview** tab](#access-your-organization-billing-information) shows an estimate of how much you may be charged at the end of this month.
This estimate is based on:
- Your organization settings (user management settings, number of projects, potential add-ons, support SLA, etc.)
- Your resource allocation on each project
The estimate includes the history of changes made since the beginning of the month.
**It cannot be 100% accurate, as it is impossible to know exactly what your future usage will be.**
However, for maximum accuracy, the current month estimate includes the following underlying estimates,
each with its own calculation:
The following formula is used to estimate how much user license and user management add-on fees may cost you this month:
unit price x prorated quantity.
Item
Description
unit price
A fixed unit price.
prorated quantity
An average of past changes and current settings, applied for all the remaining days in the month.
All items used for the calculation are displayed in the Overview tab.
The resources consumed for builds, bandwidth, and log forwarding are accumulated resources.
The following formula is used to estimate how much accumulated resource usage may cost you this month:
current accumulation + (unit price x daily average x remaining days in the month).
Item
Description
current accumulation
The amount of accumulated resources you have effectively used so far this month.
unit price
A fixed unit price.
daily average
An average based on the accumulated resource usage you’ve had over the last 30 days.
All items used for the calculation are displayed in the Overview tab.
The resources consumed by your applications and services (CPU, RAM, and storage) are allocated resources.
The following formula is used to estimate how much allocated resource usage may cost you this month:
unit price x prorated quantity.
Item
Description
unit price
A fixed unit price.
prorated quantity
An average of past changes and current settings, applied for all the remaining days in the month.
All items used for the calculation are displayed in the Overview tab.
### Next month estimate
From the [**Overview** tab](#access-your-organization-billing-information), you can also access an estimate for next month.
Like your [current month estimate](#current-month-estimate), it includes your organization settings and resource allocation on each project.
However, your next month estimate **does not include any history of changes**.
It is solely based on your current organization settings and resource allocation,
and shows what you may be charged if you don't make any changes until the end of next month.
The following formulas are used:
- `unit price x current allocation` to estimate how much user license, user management add-on fees,
and allocated resources may respectively cost you next month.
- `unit price x daily average x 30 days` to estimate how much accumulated resources may cost you next month.
### Invoice
Your invoice provides definitive information on what you will be charged.
It is calculated at month-end close, and includes your actual organization settings and resource usage.
To access your current invoice and a history of past invoices, open the **Invoices** tab:

## Manage billing alerts
Feature availability
Billing alerts can only be set and received by the organization owner,
users with the Manage Billing permission,
and identified billing contacts.
### Set a billing alert
You can set billing alerts to receive an email when your [current month estimate](#current-month-estimate) reaches a defined threshold.
Warning
Current month estimates are computed once a day only.
Therefore, email notifications can only be triggered once a day too.
You may want to increase your billing alert threshold after receiving an email notification.
However, if the new threshold is reached later on the same day,
you won’t get notified until the following day, when the current month estimate is computed again.
To set a billing alert on your organization:
1. Navigate to your organization.
2. Open the user menu (your name or profile picture).
3. Click **Billing**.
4. In the **Overview** tab, click **Set alert**.
5. Enter a threshold.
6. Click **Create alert**.
### Edit a billing alert
To edit or delete a billing alert, click the billing alert button in the **Overview** tab:

Change the monthly threshold and click **Save**, or click **Delete alert**.
To change the currency of your billing alerts, [contact support](/learn/overview/get-support.md).
Warning
After Support changes the currency, your existing billing alerts are not automatically converted to the new currency.
Edit your billing alerts to have correct amounts in the new currency.
You can track costs related to resource usage on a specific project in the [Console](/administration/web/_index.md).
To do so, after you've set or updated resources on your project:
1. Navigate to your organization.
2. Open the user menu (your name or profile picture).
3. Click **Billing**.
Your [current month estimate](#current-month-estimate) shows how much each project in your organization is expected to cost this month.
4. You can select a project to view resource allocation and usage details.
To do so, click ** More** next to it, and select **Project Billing**.

For information on resource-related costs, see the [Upsun pricing page](https://upsun.com/pricing/).
# Java [Moving a Java application to {{% vendor/name %}}](https://docs.upsun.com/languages/java/migration.html)
Note
You can now use composable image (BETA) to install runtimes and tools in your application container. To find out more, see the dedicated documentation page.
It is common to have a Java application that you want to migrate to Upsun.
Upsun supports several styles of Java application, such as monolith, microservices, stateful, and stateless.
## Minimum Requirement
To run a Java application at Upsun you need:
* [A supported Java version](/languages/java/_index.md#supported-versions)
* [A build management tool](/languages/java/_index.md#support-build-automation)
* [Gradle](https://docs.gradle.org/current/userguide/gradle_wrapper.html)
* [Maven](https://maven.apache.org/)
* [Maven Wrapper](https://www.baeldung.com/maven-wrapper)
* [Ant](https://ant.apache.org/)
* A Git Repository:
* [GitHub](/integrations/source/github.md)
* [BitBucket](/integrations/source/bitbucket.md)
* [GitLab](/integrations/source/gitlab.md)
* The default Git repository provided by Upsun
Note
A container application can’t be bigger than 8 GB of memory.
For more details, see tuning.
## Monolith/Single Application
To start a Java application, you need to understand the [Upsun structure](/learn/overview/structure.md).
You will need to configure your [application](../../create-apps/_index.md), [routes](../../define-routes/_index.md),
and [services](../../add-services/_index.md).
### Application
```yaml {configFile="app"}
applications:
myapp:
type: 'java:'
hooks:
build: [2]
web:
commands:
start: [3]
```
1. [A Java version](/languages/java/_index.md#supported-versions), e,g.: `java:21`
2. [Hooks define what happens when building the application](../../create-apps/hooks/_index.md). This build process typically generates an executable file such as a uber-jar. For example, `mvn clean package`.
3. [The commands key defines the command to launch the application](/create-apps/app-reference/single-runtime-image.md#web-commands). For example, `java -jar file.jar`.
4. In the start's command needs to receive the port where the application will execute thought the `PORT` environment. That's best when your app follows the port bind principle. For example, `java -jar jar --port=$PORT`.
### Route
```yaml {configFile="app"}
routes:
"https://{default}/":
type: upstream
upstream: "myapp:http" [1]
"https://www.{default}/":
type: redirect
to: "https://{default}/"
applications:
myapp:
type: 'java:'
hooks:
build: [2]
web:
commands:
start: [3]
```
1. It defines the application will link in the route. For example,`"myapp:http"`.
Note
Application instances have a limited amount of memory at build time, which has a maximum of 8 GB.
At runtime that limit depends on the resources you have defined for your application container using upsun resources:set.
A stateless application can be scaled horizontally to multiple application instances with upsun resources:set or by using Varnish in a load balancer configuration.
## Microservices
You have the option to use several languages in microservices. If you're using Java there are several options to aggregate these services into a microservices:
* [Maven Modules](https://maven.apache.org/guides/mini/guide-multiple-modules.html)
* [Gradle Multi-project](https://guides.gradle.org/creating-multi-project-builds/)
* [Git submodules](/development/submodules.md)
[Upsun supports multiple applications](../../create-apps/multi-app/_index.md) and there are two options:
* One application YAML file to each application
* Aggregate all applications in a single file with an `.upsun/config.yaml` file
| Article | Content |
| ------------------------------------------------------------ | ------------------------------------------------------------ |
| [Microservices in the cloud, part two](https://platform.sh/blog/2019/microservices-in-the-cloud-part-two/) | [Source](https://github.com/EventosJEspanol/latin-america-micro-profile) |
| [Microservices in the cloud, part one](https://platform.sh/blog/2019/microservices-in-the-cloud-part-one/) | [Source](https://github.com/EventosJEspanol/latin-america-micro-profile) |
| [Multiple Applications](https://community.platform.sh/t/multiple-applications-tomcat/468) | [Source](https://github.com/platformsh-examples/tomcat-multi-app) |
| [Configure multi-applications with `.upsun/config.yaml`](https://community.platform.sh/t/how-to-configure-multi-applications-with-applications-yaml/552) | [Source](https://github.com/platformsh-examples/tomcat-multi-app-applications) |
While the table above shows examples for Platform.sh rather than for Upsun, the same rules apply with only slight changes in configuration.
## Access to managed services
Upsun provides [managed services](/add-services/_index.md) such as databases, cache and search engines.
However, you can use a database or any services such as a transition process, just be aware of the [firewall](/create-apps/app-reference/single-runtime-image.md#firewall).
When applications need to access a service, it is important to include the [`relationships` key](/create-apps/app-reference/single-runtime-image.md#relationships).
By default an application may not talk to any other container without a `relationship` explicitly allowing access.
To connect to a service from your deployed application, you need to pass the relationships information into your application's configuration.
The way to do so varies with the application.
The most common mechanisms are listed below.
### Overwrite
If you are using a framework that follows the [Twelve-Factor App](https://12factor.net/) methodology, particularly the [third point](https://12factor.net/config), you can configure the application directly from environment variables.
Examples of such frameworks include Spring, Eclipse MicroProfile Config, Quarkus, and Micronauts.
Service credentials are available within the [service environment variables](/development/variables/_index.md#service-environment-variables), or the [`PLATFORM_RELATIONSHIPS` environment variable](/development/variables/use-variables.md#use-provided-variables).
Assuming the relationship postgresql is configured to grant access to a PostgreSQL service container, you can map the automatically generated environment variable (POSTGRESQL_HOST) to whatever your application expects to use:
While the table above shows examples for Platform.sh rather than for Upsun, the same rules apply with only slight changes in configuration.
To reduce the number of lines in the application file and to make it cleaner,
you have the option to move the variable environment to another file: a [`.environment` file](../../development/variables/set-variables.md#set-variables-via-script).
**Example:**
You can obtain relationship information through the [service environment variables](/development/variables/_index.md#service-environment-variables) themselves,
or through the [`PLATFORM_RELATIONSHIPS` environment variable](/development/variables/use-variables.md#use-provided-variables).
Say your application has a relationship named ``postgresql`` to a database service named `postgresql`:
This PLATFORM_RELATIONSHIPS variable is a base64-encoded JSON object with keys of the relationship name and values of arrays of relationship endpoint definitions.
Upsun supports the jq tool, which allows to extract information from this JSON.
This `.environment` file can interact to each application file.
**Example:**
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
myapp:
type: 'java:21'
hooks:
build: ./mvnw package -DskipTests -Dquarkus.package.uber-jar=true
relationships:
postgresql:
web:
commands:
start: java -jar $JAVA_OPTS $CREDENTIAL -Dquarkus.http.port=$PORT jarfile.jar
```
# Java [Performance tuning Java](https://docs.upsun.com/languages/java/tuning.html)
Note
You can now use composable image (BETA) to install runtimes and tools in your application container. To find out more, see the dedicated documentation page.
There are a number of settings that can be adjusted for each application to optimize its performance on Upsun.
## Memory limits
The JVM generally requires specifying a maximum memory size it is allowed to use, using the `Xmx` parameter.
That should be set based on the available memory on the application container, which varies with its size.
To extract the container-scaled value on the command line, use `$(jq .info.limits.memory /run/config.json)`.
You should also set the `ExitOnOutOfMemoryError`.
When you enable this option, the JVM exits on the first occurrence of an out-of-memory error.
Upsun will restart the application automatically.
These are the recommended parameters for running a Java application. Thus, the command to use to start a Java application is:
```bash
java -jar -Xmx$(jq .info.limits.memory /run/config.json)m -XX:+ExitOnOutOfMemoryError //The rest of the arguments and the jar file.
```
## Garbage collection
When migrating the application to a cloud environment, it is often essential to analyze the Garbage Collector's log and behavior. For this, there are two options:
* Placing the log into the Upsun `/var/log/app.log` file (which captures `STDOUT`).
* Creating a log file specifically for the GC.
To use the `STDOUT` log, you can add the parameter `-XX: + PrintGCDetails`, E.g.:
```bash
java -jar -Xmx$(jq .info.limits.memory /run/config.json)m -XX:+ExitOnOutOfMemoryError -XX:+PrintGCDetails //The rest of the arguments and the jar file.
```
Java supports a number of different garbage collection strategies.
Which one is optimal for your application varies depending on your available memory, Java version, and application profile.
Determining which is best for your application is out of scope, but the main options and how to enable them are:
| Name | Command Flag | Description |
| ------------- |:-------------:| -----:|
|Serial Garbage Collector|-XX:+UseSerialGC|This is the simplest GC implementation, as it basically works with a single thread.|
|Parallel Garbage Collector|-XX:+UseParallelGC|Unlike Serial Garbage Collector, this uses multiple threads for managing heap space. But it also freezes other application threads while performing GC.|
|CMS Garbage Collector|-XX:+USeParNewGC|The Concurrent Mark Sweep (CMS) implementation uses multiple garbage collector threads for garbage collection. It's for applications that prefer shorter garbage collection pauses, and that can afford to share processor resources with the garbage collector while the application is running.|
|G1 Garbage Collector|-XX:+UseG1GC|Garbage First, G1, is for applications running on multiprocessor machines with large memory space.|
The default strategy on Java 9 and later is G1.
The GC strategy to use can be set in the start line with:
### Serial
```bash
java -jar -Xmx$(jq .info.limits.memory /run/config.json)m -XX:+ExitOnOutOfMemoryError -XX:+PrintGCDetails -XX:+UseSerialGC //The rest of the arguments and the jar file.
```
### Parallel Garbage Collector
```bash
java -jar -Xmx$(jq .info.limits.memory /run/config.json)m -XX:+ExitOnOutOfMemoryError -XX:+PrintGCDetails -XX:+UseParallelGC //The rest of the arguments and the jar file.
```
### CMS Garbage Collector
```bash
java -jar -Xmx$(jq .info.limits.memory /run/config.json)m -XX:+ExitOnOutOfMemoryError -XX:+PrintGCDetails -XX:+USeParNewGC //The rest of the arguments and the jar file.
```
### G1
```bash
java -jar -Xmx$(jq .info.limits.memory /run/config.json)m -XX:+ExitOnOutOfMemoryError -XX:+PrintGCDetails -XX:+UseG1GC //The rest of the arguments and the jar file.
```
## Java 8 Optimization
Ideally, all applications should run the latest LTS release of the JVM at least.
That is currently Java 11.
Java 11 has a number of performance improvements, particularly on container-based environments such as Upsun.
However, in many cases, this isn't possible.
If you are still running on Java 8 there are two additional considerations.
The default garbage collector for Java 8 is Parallel GC.
In most cases G1 will offer better performance.
We recommend enabling it, as above.
Furthermore, there is the `UseStringDeduplication` flag which works to eliminate duplicate `String`s within the GC process.
That flag can save between 13% to 30% of memory, depending on application. However, this can impact on the pause time of your app.
```bash
java -jar -Xmx$(jq .info.limits.memory /run/config.json)m -XX:+UseG1GC -XX:+UseStringDeduplication -XX:+ExitOnOutOfMemoryError -XX:+PrintGCDetails
```
## References
* [Introduction to Garbage Collection Tuning](https://docs.oracle.com/en/java/javase/14/gctuning/introduction-garbage-collection-tuning.html#GUID-326EB4CF-8C8C-4267-8355-21AB04F0D304)
# Tutorials [Restrict access to a service](https://docs.upsun.com/learn/tutorials/restrict-service-access.html)
Upsun allows you to restrict access to a service.
In this tutorial, learn how to grant your Data team `read-only` access to your production database.
## Before you start
You need:
- A project with a database service
- A `viewer` user on your project
## 1. Add a read-only endpoint to your database service
Edit your `.upsun/config.yaml` file and add the following [endpoints](/add-services/mysql/_index.md#define-permissions):
- `website` with `admin` access to the `main` database
- `reporting` with read-only `ro` access to the `main` database
```yaml {configFile="services"}
services:
maindb:
type: mariadb:10.5
configuration:
schemas:
- main
endpoints:
website:
default_schema: main
privileges:
main: admin
reporting:
privileges:
main: ro
```
## 2. Grant your app access to the new endpoints
Edit your app configuration and add new relationships to your new endpoints:
```yaml {configFile="app"}
applications:
myapp:
# ...
relationships:
database:
service: maindb
endpoint: website
reports:
service: maindb
endpoint: reporting
```
## 3. Create a worker with access to the read-only endpoint
Edit your app configuration to add a new worker which:
- Does nothing (`sleep infinity`)
- Can access the read-only `reporting` endpoint
- Allows SSH access to `viewer`
```yaml {configFile="app"}
applications:
myapp:
workers:
data_access:
mounts: {}
commands:
start: |
sleep infinity
relationships:
reports:
service: maindb
endpoint: reporting
access:
ssh: viewer
```
You're done!
From now on, your `viewer` users can SSH in to the worker application,
and connect to your database with read-only permissions.
# What is Upsun? [Structure](https://docs.upsun.com/learn/overview/structure.html)
Each environment you deploy on Upsun is built as a set of containers.
Each container is an isolated instance with specific resources.
Each environment has 2 to 4 types of containers, all usually configured from your `.upsun/config.yaml` file.
- One [*router*](#router)
- One or more [*app* containers](#apps)
- Zero or more [*service* containers](#services)
- Zero or more [*worker* containers](#workers)
If you have two app containers, two services (a database and a search engine), and a worker,
requests to your environment might look something like this:

If you have only one app container, your repository might look like this:
```text
project
├── .git
├── .upsun
│ └── config.yaml
└──
```
## Router
Each environment always has exactly one router.
This router maps incoming requests to the appropriate app container
and provides basic caching of responses, unless configured otherwise.
The router is configured in a `.upsun/config.yaml` file.
If you don't include configuration, a single [default route is deployed](/define-routes/_index.md#default-route-definition).
Read more about how to [define routes](/define-routes/_index.md).
## Apps
You always need at least one app container, but you can have more.
App containers run the code you provide via your Git repository.
They handle requests from the outside world and can communicate with other containers within the environment.
Each app container is built from a specific language image with a given version for the language.
To configure your apps, you usually create a single `.upsun/config.yaml` file
and place it in the repository root.
Read more about how to [configure apps](/create-apps/_index.md).
## Services
You don't need any service containers, but you can add them as you like.
Service containers run predefined code for specific purposes, such as a database or search service.
You don't need to add their code yourself, just set up how your apps communicate with them.
Service containers are configured by the `.upsun/config.yaml` file.
Read more about how to [add services](/add-services/_index.md).
## Workers
You don't need any worker containers, but you can add them as you like.
Worker containers are copies of an app containers
that have no access to the outside world and can have a different start command.
They're useful for continually running background processes.
Read more about how to [work with workers](/create-apps/workers.md).
# Set up your local development environment [Tethered local development](https://docs.upsun.com/development/local/tethered.html)
To test changes locally, you can connect your locally running web server
to service containers on an active Upsun environment.
This method requires less configuration than tools such as [DDEV](./ddev.md),
but may not perform well enough for everyday use.
Because it replies on a local web server, it's also less consistent across your team.
## Before you begin
You need:
- A local copy of the repository for a project running on Upsun.
To get one, run upsun
get PROJECT_ID.
Alternatively, you can clone an integrated source repository and set the remote branch.
To do so, run upsun
project:set-remote PROJECT_ID.
- The [Upsun CLI](/administration/cli/_index.md)
## Create the tethered connection
1. Create a new environment based on production.
```bash
upsun branch new-feature PRODUCTION_ENVIRONMENT_NAME
```
If you're using a [source integration](/integrations/source.html),
open a merge/pull request.
1. To open an SSH tunnel to the new environment's services, run the following command:
```bash
upsun tunnel:open
```
This command returns the addresses for SSH tunnels to all of your services.
1. Export the `PLATFORMSH_RELATIONSHIPS` environment variable with information from the open tunnel:
```bash
export PLATFORM_RELATIONSHIPS="$(upsun tunnel:info --encode)"
```
1. Run your application locally.
Make sure it's set up to read configuration from Upsun environment variables.
If you app relies on other Upsun environment configuration, such as routes or secret variables,
make sure to mock those variables as well.
Your options for running the app depend on the language and configuration.
You can use the server for your language, install a copy of Nginx,
or use a virtual machine or Docker image.
1. When you've finished your work, close the tunnels to your services by running the following command:
```bash
upsun tunnel:close --all -y
```
## Connect to services directly
With open tunnels to all your services, you can also connect to the running services directly.
To get information on all running services, run the following command:
```bash
upsun tunnels
```
You get a response similar to the following:
```bash
+-------+---------------+-------------+-----+--------------+
| Port | Project | Environment | App | Relationship |
+-------+---------------+-------------+-----+--------------+
| 30000 | abcdefg123456 | new-feature | app | cache |
| 30001 | abcdefg123456 | new-feature | app | database |
+-------+---------------+-------------+-----+--------------+
```
You can use the port information to connect directly to a service.
If you need more detailed information, such as a path or password, run the following command:
```bash
upsun tunnel:info
```
You can use the information returned to connect to the remote database as if it were local.
For example, the following command would connect to a MySQL database running through a tethered connection:
```bash
mysql --host=127.0.0.1 --port=PORT --user=USERNAME --password=PASSWORD --database=PATH
```
## Next steps
You can now use your local environment to develop changes for review on Upsun environments.
The following examples show how you can take advantage of that.
### Onboard collaborators
It's essential for every developer on your team to have a local development environment to work on.
Place the local configuration into a script to ensure everyone has this.
You can merge this change into production.
1. Create a new environment called `local-config`.
1. To set up a local environment for a new Upsun environment, create an executable script.
```bash
touch init-local.sh && chmod +x init-local.sh
```
1. Fill it with something similar to the following example, depending on your app and configuration:
```bash {location="init-local.sh"}
#!/usr/bin/env bash
ENVIRONMENT=$1
PARENT=$2
# Create the new environment
upsun branch $ENVIRONMENT $PARENT
# Open a tunnel to the current environment
upsun tunnel:open --no-interaction
# Mock Upsun environment variables
export PLATFORM_RELATIONSHIPS="$(upsun tunnel:info --encode)"
# Add any other variables you need
# If necessary, install dependencies here
# Add the command to run the server
```
1. To commit and push the revisions, run the following command:
```bash
git add . && git commit -m "Add local configuration" && git push upsun local-config
```
1. Merge the change into production.
Once the script is merged into production,
any user can set up their local environment by running the following commands:
```bash
upsun PROJECT_ID
cd PROJECT_NAME
./init-local.sh PROJECT_ID another-new-feature PRODUCTION_ENVIRONMENT_NAME
```# Set up your local development environment [Untethered local development](https://docs.upsun.com/development/local/untethered.html)
It's possible to run your entire site locally on your computer.
That way you get better performance as there's no extra latency to connect to a remote database and doesn't require an active Internet connection to work.
But it does require running all necessary services (databases, search servers, and so on) locally.
These can be set up however you prefer, although Upsun recommends using a virtual machine to make it easier to share configuration between developers.
If you already have a development workflow in place that works for you, you can keep using it with virtually no changes.
To synchronize data from an environment on Upsun, consult the documentation for each [service](../../add-services/_index.md).
Each service type has its own native data import/export process and Upsun doesn't get in the way of that.
It's also straightforward to [download user files](/learn/tutorials/exporting.md) from your application using rsync.
# What is Upsun? [Build and deploy](https://docs.upsun.com/learn/overview/build-deploy.html)
Each time you push a change to your app through Git or activate an [environment](/environments/_index.md),
your app goes through a process to be built and deployed.
If your app is redeployed with no changes to its codebase, the output of the previous build and deploy process is reused.
The build process looks through the configuration files in your repository and assembles the necessary containers.
The deploy process makes those containers live, replacing any previous versions, with minimal interruption in service.

Hooks are points in the build and deploy process where you can inject a custom script.
## The build
The outcome of the build process is designed to be repeatable and reusable.
Each app in a project is built separately.
Container configuration depends exclusively on your configuration files.
So each container is tied to a specific Git commit.
If there are no new changes for a given container, the existing container can be reused.
This saves you the time the build step would take.
This means the build is independent of the given environment and preview environments are perfect copies of production.
If you use environment variables to set up different build configuration options for different environments,
your build step isn't reused and your preview environments may differ from production.
You can't connect to services (like databases) during the build step.
Once the app has gone through all of the build steps, it can connect to services in the deploy process.
### Build steps
1. **Validate configuration**:
The configuration is checked by validating the `.upsun` directory and scanning the repository for any app configuration to validate.
2. **Pull container images**:
Any container images that have been built before and that don't have any changes are pulled to be reused.
3. **Install dependencies**:
If you have specified additional global dependencies, they're downloaded during this step.
This is useful for commands you may need in the build hook.
4. **Run build flavor commands**:
For some languages (NodeJS, PHP), a series of standard commands are run based on the build flavor.
You can change the flavor or skip the commands by specifying it in your `.upsun/config.yaml` file.
5. **Run build hook**:
The `build` hook comprises one or more shell commands that you write to finish creating your production code base.
It could be compiling Sass files, running a bundler, rearranging files on disk, or compiling.
The committed build hook runs in the build container.
During this time, commands have write access to the file system, but there aren't connections to other containers (services and other apps).
Note that you can [cancel deployments stuck on the build hook](/environments/cancel-activity.md).
6. **Freeze app container**:
The file system is frozen and produces a read-only container image, which is the final build artifact.
## The deploy
The deploy process connects each container from the build process and any services.
The connections are defined in your app and services configuration.
So unlike the build process, you can now access other containers,
but the file system is read-only.
### Deploy steps
1. **Hold requests**:
Incoming [idempotent requests](https://www.iana.org/assignments/http-methods/http-methods.xhtml) (like `GET`, `PUT`, `DELETE` but **not** `POST`, `PATCH` etc.) are held.
1. **Unmount current containers**:
Any previous containers are disconnected from their file system mounts.
1. **Mount file systems**:
The file system is connected to the new containers.
New branches have file systems cloned from their parent.
1. **Expose services**:
Networking connections are opened between any containers specified in your app and services configurations.
1. **Run (pre-) start commands**:
The [commands](/create-apps/app-reference/single-runtime-image#web-commands) necessary to start your app are run.
Often this stage will only include a start command, which is restarted if ever terminated going forward.
You may also, however, define a `pre_start` command, when you need to run _per-instance_ actions.
In this case, as you might expect, the `pre_start` command is run, then the `start` command.
1. **Run deploy hook**:
The `deploy` hook is any number of shell commands you can run to finish your deployment.
This can include clearing caches, running database migrations, and setting configuration that requires relationship information.
1. **Serve requests**:
Incoming requests to your newly deployed application are allowed.
After the deploy process is over, any commands in your `post_deploy` hook are run.
## Deployment philosophy
Upsun values consistency over availability, acknowledging that it's nearly impossible to have both.
During a deployment, the [deploy hook](/create-apps/hooks/hooks-comparison.md#deploy-hook) may make database changes
that are incompatible with the previous code version.
Having both old and new code running in parallel on different servers could therefore result in data loss.
Upsun believes that a minute of planned downtime for authenticated users is preferable to a risk of race conditions
resulting in data corruption, especially with a CDN continuing to serve anonymous traffic uninterrupted.
That brief downtime applies only to the environment changes are being pushed to.
Deployments to a staging or development branch have no impact on the production environment and cause no downtime.
## What's next
* See how to [configure your app](/create-apps/_index.md) for the entire process.
* Learn more about [using build and deploy hooks](/create-apps/hooks/_index.md).
# Console [Configure environments](https://docs.upsun.com/administration/web/configure-environment.html)
From your project's main page in the Console, you can see all your environments as a list or a project tree:

In this overview, the names of inactive environments are lighter.
Selecting an environment allows you to see details about it,
such as its [activity feed](#activity-feed), [services](#service-information),
[metrics](../../increase-observability/metrics/_index.md), and [backups](../../environments/backup.md).
## Activity Feed
When you access an environment in the Console, you can see its [activity feed](../../increase-observability/logs/access-logs.md#activity-logs).
This allows you to check which activities have happened or are currently happening on the selected environment:

You can filter activities by type (such as merge, sync, or redeploy).
## Actions on environments
Each environment offers ways to keep environments up to date with one another:
* [ **Branch**](/glossary.md#branch) to create a new child environment.
* [ **Merge**](/glossary.md#merge) to copy the current environment into its parent.
* [ **Sync**](/glossary.md#sync)
to copy changes from its parent environment into the current environment.
There are also additional options:
* **Settings** to [configure the environment](#environment-settings).
* **More** to get more options.
* **URLs** to access the deployed environment from the web.
* **SSH** to access your project using SSH.
* **Code**
* **CLI** for the command to get your project set up locally with the [Upsun CLI](../cli/_index.md).
* **Git** for the command to clone the codebase via Git.
If you're using Upsun as your primary remote repository, the command clones from the project.
If you have set up an [external integration](../../integrations/source/_index.md),
the command clones directly from the integrated remote repository.
If the project uses an external integration to a repository that you haven't been given access to,
you can't clone until your access has been updated.
See how to [troubleshoot source integrations](../../integrations/source/troubleshoot.md).
## Environment URL
When you access an environment in the Console, you can view its URL:

While the environment is loading in the Console, a `Waiting for URL...` message is displayed instead of the URL.
If this message isn't updated once your [default environment](../../environments/_index.md#default-environment)'s information is loaded,
follow these steps:
1. Check that [you have defined routes](../../define-routes/_index.md) for your default environment.
2. Verify that your [application](/create-apps/app-reference/single-runtime-image.md), [services](../../add-services/_index.md), and [routes](../../define-routes/_index.md) configurations are correct.
3. Check that your default environment is [active](../../environments/deactivate-environment.md#reactivate-an-environment).
## Environment settings
To access the settings of an environment, click **Settings** within that environment.

### Environment name
Under **Environment name**, you can edit the name and type of your environment and view its parent environment:

### Status
Under **Status**, you can check whether or not your environment is [active](/glossary.md#active-environment).

For preview environments, you can [change their status](../../environments/deactivate-environment.md).
### Outgoing emails
Under **Outgoing emails**, you can allow your environment to [send emails](../../development/email.md):

### Hide from search engines
Under **Hide from search engines**, you can tell [search engines to ignore the site](../../environments/search-engine-visibility.md):

### HTTP access control
Under **HTTP access control**, you can [control access to your environment using HTTP methods](../../environments/http-access-control.md):

### Variables
Under **Variables**, you can define [environment variables](../../development/variables/_index.md):

## Service information
For each environment, you can view information about how your routes, services, and apps are currently configured.
To do so, click **Services**.
By default, you see configured routes.
### Routes
The **Router** section shows a list of all the [routes configured on your environment](../../define-routes/_index.md).
You can see each route's type and check if caching and server side includes have been enabled for it:

To view the configuration file where your routes are set up, click **Configuration**.
### Applications
To see detailed information about an app container,
select it in the tree or list on the left-hand side:

The **Overview** tab gives you information about your app.
You can see:
* The language version, the container size, the amount of persistent disk,
the number of cron jobs, and the command to SSH into the container.
* A summary of [metrics for the environment](../../increase-observability/metrics/_index.md).
* All cron jobs with their name, frequency, and command.
* All workers with their name, size, amount of persistent disk, and command to SSH into the container.
To view [the configuration file where your app is set up](../../create-apps/), click **Configuration**.
### Services
To see detailed information about a [running service](../../add-services/_index.md),
select it in the tree or list on the left-hand side:

The **Overview** gives you information about the selected service.
You can see the service version, the container size, and the disk size, if you've configured a persistent disk.
You can also see a summary of [metrics for the environment](../../increase-observability/metrics/_index.md).
To view the configuration file where your services are set up, click **Configuration**.
# Define routes [HTTPS](https://docs.upsun.com/define-routes/https.html)
Using HTTPS for your site helps ensure your users' information remains secure.
HTTPS provides enhanced security thanks to the following characteristics:
- With HTTPS, data is encrypted so user activity can't be tracked and user information can't be stolen.
- HTTPS prevents the corruption of files transferred from a web server to a website and vice-versa.
- HTTPS also authenticates websites, which helps build trust with your users.
To enable HTTPS on your site, you need [Transport Layer Security (TLS) certificates](#tls-certificates).
## TLS certificates
Upsun automatically provides TLS certificates for all sites and environments.
These certificates are issued at no charge by [Let's Encrypt](https://letsencrypt.org/) and cover most needs.
They're valid for 90 days and automatically renewed 28 days before expiration.
To use them, you only need to [specify HTTPS routes](../define-routes/https.md#enable-https).
Note that [limitations](../define-routes/https.md#lets-encrypt-limitations) apply.
If you encounter issues with the TLS certificates provided by Upsun,
check that [TLS encryption is up-and-running](../domains/troubleshoot.md#verify-ssltls-encryption).
If you don't want to use the TLS certificates provided by Upsun,
configure your own [third-party TLS certificates](../domains/steps/tls.md).
### Let's Encrypt limitations
When you use the Let's Encrypt [TLS certificates](#tls-certificates) provided by Upsun,
the following limitations apply.
Let's Encrypt allows a maximum of 100 hostnames per certificate.
You can have 1 Let's Encrypt certificate for each of your environments.
If you define both a `{default}` and a `www.{default}` route for each domain you use,
you can add up to 50 hostnames.
Going over this limitation results in a warning on deploy and no new TLS certificates are issued.
If you need more hostnames, you can obtain additional certificates
or a wildcard certificate from a [third-party issuer](../domains/steps/tls.md).
Alternatively, consider splitting your project up into multiple Upsun projects.
Please note that when using multiple domains, the Common Name (CN) to which the certificate is issued to
is not guaranteed to be the same on each certificate renewal.
### Certificate renewals
When you use the [TLS certificates](#tls-certificates) provided by Upsun,
certificate renewals are automatic.
They trigger a redeployment of your environment.
During this redeployment, required security and system upgrades are applied to your containers.
So the duration of the redeployment depends on what needs to be upgraded.
## Enable HTTPS
To enable HTTPS, add a routing configuration similar to the following:
```yaml {configFile="routes"}
routes:
"https://{default}/":
type: upstream
upstream: "myapp:http"
"https://www.{default}/":
type: redirect
to: "https://{default}/"
```
All traffic to your domain is then sent to your app.
The `www` subdomain redirects to the [default domain](../define-routes/_index.md#default).
This also includes redirecting requests from HTTP to HTTPS.
For more information, see how to [define routes](../define-routes/_index.md).
## Optional: Configure TLS connections
When you [specify HTTPS routes](#enable-https),
you can use the `tls` setting to further configure your TLS connections.
### Enforce TLS 1.3
Although you can still use TLS 1.2, TLS 1.3 is faster and more secure.
To instruct your web server to automatically reject TLS 1.2 connections,
enforce TLS 1.3 using the `min_version` setting:
```yaml {configFile="routes"}
routes:
"https://{default}/":
# ...
tls:
min_version: TLSv1.3
```
Note that TLS versions older than 1.2 are deprecated and are rejected by default.
### Enable HTTP Strict Transport Security (HSTS)
[HSTS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security) forces clients to always communicate with your site over HTTPS.
To enable HSTS, use `strict_transport_security` in a configuration similar to the following:
```yaml {configFile="routes"}
routes:
"https://{default}/":
# ...
tls:
strict_transport_security:
enabled: true
include_subdomains: true
preload: true
```
The following table presents the possible properties for `strict_transport_security`:
| Name | Type | Default | Description |
|----------------------|-----------|---------|------------------------------------------------------------------------------------------------|
| `enabled` | `boolean` | `null` | If set to `true`, HSTS is enabled for 1 year. If set to `false`, other properties are ignored. |
| `include_subdomains` | `boolean` | `false` | To specify whether HSTS applies to all subdomains. |
| `preload` | `boolean` | `false` | To add your website to the [HSTS preload list](https://hstspreload.org/). Thanks to this list, most browsers are informed that your site requires HSTS before an HSTS header response is even issued. |
Note that when you enable or disable HSTS, the entire domain is affected.
Make sure you only add the HSTS configuration to a single route.
Having different routes with conflicting HSTS configurations can cause issues.
### Enable mTLS
Standard TLS connections are useful to verify the identity of web servers and their certificates.
But you can also instruct your web server to verify the identity of clients and their certificates.
This allows you to restrict access to trusted users.
To do so, enable mTLS by adding the following configuration:
```yaml {configFile="routes"}
routes:
"https://{default}/":
# ...
tls:
client_authentication: "require"
```
By default, all valid TLS certificates issued by a legitimate certificate authority are accepted.
But you can instruct your web server to only accept TLS certificates issued by specific or even custom certificate authorities.
To do so, add a configuration similar to the following:
```yaml {configFile="routes"}
routes:
"https://{default}/":
# ...
tls:
client_authentication: "require"
client_certificate_authorities:
- !include
type: string
path: root-ca1.crt
- !include
type: string
path: root-ca2.crt
```
In this case, the certificate files are resolved relative to the `.upsun` directory.
Alternatively, you can specify the certificates inline in the file:
```yaml {configFile="routes"}
routes:
"https://{default}/":
# ...
tls:
client_authentication: "require"
client_certificate_authorities:
- |
-----BEGIN CERTIFICATE-----
### Several lines of characters here ###
-----END CERTIFICATE-----
- |
-----BEGIN CERTIFICATE-----
### Several lines of different characters here ###
-----END CERTIFICATE-----
```
# Best practices [Keep your Git repository clean](https://docs.upsun.com/learn/bestpractices/clean-repository.html)
When a Git repository contains a high number of references and files, the performance of Git can decrease.
This is why most Git providers have repository size limits in place (for more information, see the [GitHub](https://docs.github.com/en/repositories/working-with-files/managing-large-files/about-large-files-on-github), [GitLab](https://docs.gitlab.com/ee/user/gitlab_com/index.html#account-and-limit-settings)
and [Bitbucket](https://support.atlassian.com/bitbucket-cloud/docs/reduce-repository-size/) documentation).
The Upsun API and [Console](/administration/web/_index.md) are closely tied to Git.
When the performance of Git decreases, Upsun API servers also become slower.
As a user, you can then experience significant latencies.
If your repository becomes too large, your Console may even become unresponsive,
leaving you unable to access your project.
To avoid such issues, make sure you keep your Git repository clean by following the instructions on this page.
If you're already facing performance issues and suspect they might be related to the size of your Git repository,
see how you can [troubleshoot a sizeable Git repository](#troubleshoot-a-sizeable-git-repository).
## Enable the automated pruning of old branches in your project
To keep your repository size to a minimum,
make sure that branches that don't exist anymore in your repository have also been deleted from Upsun.
To automate this process, when setting up a [source integration](/integrations/_index.md),
enable the `prune-branches` option.
If you already have a source integration set up and want to enable the `prune-branches` option,
follow these steps:
Click Integrations and select your source integration.
Click Edit.
Enter your access token and click Continue.
Select your repository and check the following boxes:
Fetch branches from the remote repository to your project (fetch-branches option, mandatory to enable prune-branches).
Remove branches from your project that have disappeared remotely (requires the fetch branches option to be enabled) (prune-branches option).
Click Save.
## Upload your files through mounts
Keeping too many files, especially large binary files, in your Git repository can cause performance and stability issues.
Therefore, Upsun recommends that you only commit your source code in Git.
To upload any other files to your app, [create mounts](https://docs.platform.sh/create-apps/app-reference.html#mounts)
and [transfer your files directly to them](https://docs.platform.sh/development/file-transfer.html#transfer-a-file-to-a-mount).
## Troubleshoot a sizeable Git repository
If you're experiencing latencies or can't access your Console anymore,
your Git repository may have become too large and may need to be cleaned up.
To do so, follow these instructions:
1. Remove old, unwanted files from your repository (especially large files).
You can do it manually, or use a tool such as [BFG Repo-Cleaner](https://rtyley.github.io/bfg-repo-cleaner/).
2. Remove stale branches from your repository and Upsun project.
3. Rebase and/or squash commits to clean up your history.
4. Make sure you [enable the automated pruning of old branches in your project](#enable-the-automated-pruning-of-old-branches-in-your-project)
and [upload your files through mounts](#upload-your-files-through-mounts) to avoid facing the same situation in the future.# PHP [PHP performance tuning](https://docs.upsun.com/languages/php/tuning.html)
Note
You can now use composable image (BETA) to install runtimes and tools in your application container. To find out more, see the dedicated documentation page.
Once your app is up and running it still needs to be kept fast.
Upsun offers a wide degree of flexibility in how PHP behaves,
but that does mean you may need to take a few steps to ensure your site is running optimally.
The following recommendations are guidelines only.
They're also listed in about the order to investigate them.
## Upgrade to PHP 8
To make a PHP-based site run faster, the first step is to upgrade the PHP version.
Upgrading the PHP version might require changes to your app.
For more details and recommendations, see the [PHP migration guides](https://www.php.net/manual/en/migration80.php).
To change your PHP version, change the [`type` in your app configuration](/create-apps/app-reference/single-runtime-image.md#types).
Before merging to production, test the change on a branch and make sure that your app is working as expected.
## Optimize the FPM worker count
PHP-FPM uses a fixed number of simultaneous worker processes to handle incoming requests.
If more simultaneous requests are received than the number of workers,
then some requests wait until worker processes are available.
The default worker count is set to a conservative default value.
To determine and set the optimal value for your app, see [PHP-FPM sizing](./fpm.md).
## OPcache preloading
OPcache preloading loads selected files into shared memory,
making their content (functions, classes) globally available for requests.
It also removes the need to include these files later.
When OPcache is correctly configured, it can result in significant improvements to both CPU and memory usage.
Consult your framework's documentation to see
if there are recommendations for optimal preload configuration or ready-to-use preload scripts.
OPcache is only available on PHP 7.4+ and uses PHP-CGI.
If your PHP version doesn't support OPcache, this is a good reason to upgrade.
Note that the only way to clear the preload cache is by [restarting PHP-FPM](#restart-php-fpm).
If you have [disabled OPcache timestamp validation](#disable-opcache-timestamp-validation),
you need to clear the OPcache explicitly on deployment (which can be done by restarting PHP-FPM).
### Enable OPcache preloading
To enable preloading, add a variable that specifies a preload script:
```yaml {configFile="app"}
applications:
myapp:
type: 'php:8.4'
variables:
php:
opcache.preload: 'PRELOAD_SCRIPT'
```
`PRELOAD_SCRIPT` is a file path relative to the [app root](/create-apps/app-reference/single-runtime-image.md#root-directory).
It may be any PHP script that calls `opcache_compile_file()`.
The following example uses a `preload.php` file as the preload script.
This script loads all `.php` files in the `vendor` directory (and subdirectories):
```php {location="preload.php"}
$file) {
// This is the important part!
opcache_compile_file($file[0]);
}
```
### Configure OPcache
OPcache needs to be tuned before production usage and can be configured the [same way as PHP](./_index.md#customize-php-settings).
Let the app run for a while before tuning OPcache
since the preload script may change some of the configuration.
#### Set the maximum number of cached files
`opcache.max_accelerated_files` is the maximum number of files that OPcache can cache at once.
If this value is lower than the number of files in the app,
the cache becomes less effective because it starts [thrashing](https://en.wikipedia.org/wiki/Thrashing_(computer_science)).
To determine the maximum number of files to cache, follow these steps:
1. Connect to the container via SSH using the [CLI](../../development/ssh/_index.md)
by running `upsun ssh`.
2. Determine roughly how many `.php` files your app has by running this command from [your app root](/create-apps/app-reference/single-runtime-image.md#root-directory):
```bash
find . -type f -name '*.php' | wc -l
```
Note that the returned valued is an approximation.
Some apps have PHP code in files that don't end in `.php` or files that are generated at runtime.
3. Set `opcache.max_accelerated_files` to a value slightly higher than the returned number.
PHP automatically rounds the value up to the next highest prime number.
An example configuration:
```yaml {configFile="app"}
applications:
myapp:
type: 'php:8.4'
variables:
php:
'opcache.max_accelerated_files': 22000
```
#### Set memory consumption
`opcache.memory_consumption` is the total memory (in megabytes) that OPcache can use with FastCGI.
If the app uses more than this, the cache starts [thrashing](https://en.wikipedia.org/wiki/Thrashing_(computer_science)) and becomes less effective.
Determining the optimal limit to memory consumption requires executing code via a web request to get adequate statistics.
[CacheTool](https://github.com/gordalina/cachetool) is an open-source tool to help you get the statistics.
To determine the total amount of memory to use, follow these steps:
1. Connect to the container via SSH using the [CLI](../../development/ssh/_index.md)
by running `upsun ssh`.
2. Change to the `/tmp` directory (or any other non-web-accessible writable directory) with `cd /tmp`.
3. Download CacheTool with `curl -sLO https://github.com/gordalina/cachetool/releases/latest/download/cachetool.phar`.
4. Make CacheTool executable with `chmod +x cachetool.phar`.
5. Check the OPcache status for FastCGI commands by running the following command:
```bash
php cachetool.phar opcache:status --fcgi=$SOCKET
```
The `--fcgi=$SOCKET` option ensures the PHP-FPM process on the server connects through the right socket.
6. Analyze the output to determine the optimal value for `opcache.memory_consumption`.
The most important values from CacheTool's output are the following:
- `Memory used`
- `Memory free`
- `Oom restarts` (out of memory restarts)
If the value is different than 0, you don't have enough memory allocated to OPcache.
If `Memory free` is too low or `Oom Restarts` too high,
set a higher value for memory consumption.
7. Set `opcache.memory_consumption`.
Note: The unit for `opcache.memory_consumption` is megabytes.
An example configuration:
```yaml {configFile="app"}
applications:
myapp:
type: 'php:8.4'
variables:
php:
'opcache.memory_consumption': 96
```
8. [Restart PHP-FPM](#restart-php-fpm) and make sure that OPcache works as expected by rerunning CacheTool
with the following command:
```bash
php cachetool.phar opcache:status --fcgi=$SOCKET
```
9. Remove CacheTool by deleting the `cachetools.phar` file with `rm -rf cachetools.phar`.
### Disable OPcache timestamp validation
By default, OPcache checks that the cached version of a file is always up-to-date.
This means that every time a cached file is used, OPcache compares it to the file on disk.
If that file has changed, it gets reloaded and re-cached.
This allows to support apps that generate compiled PHP code from user configuration.
If you know your code isn't going to change outside a new deployment,
you can disable that check and get a small performance improvement.
Timestamp validation can be disabled by adding the following variable to your [app configuration](../../create-apps/_index.md):
```yaml {configFile="app"}
applications:
myapp:
type: 'php:8.4'
variables:
php:
'opcache.validate_timestamps': 0
```
When you have disabled OPcache timestamp validation,
you need to explicitly clear OPcache on deployment by [restarting PHP-FPM](#restart-php-fpm).
Note: If your app generates PHP code at runtime based on user configuration, don't disable timestamp validation.
Doing so would prevent updates to the generated code from being loaded.
## Restart PHP-FPM
To force a restart of PHP-FPM:
1. Connect to your app container via SSH using the [CLI](../../development/ssh/_index.md) by running `upsun ssh`.
2. Run `pkill -f -u "$(whoami)" php-fpm`.
## Optimize your code
To optimize your app, consider using a [profiler](../../increase-observability/application-metrics/_index.md).
A profiler helps determine what slow spots can be found and addressed and helps improve performance.
# Set up a custom domain [Set up a custom domain on a preview environment](https://docs.upsun.com/domains/steps/custom-domains-preview-environments.html)
[Preview environments](/glossary.md#preview-environment) in your project can't use the custom domain [set up on your production environment](../steps/_index.md).
By default and for each preview environment,
Upsun automatically replaces the custom production domain
with an automatically generated URL.
If you don't want to use these default URLs,
you can add a custom domain to each of your preview environments
(`staging` or `development` [environment types](/glossary.md#environment-type)).
To do so, no need to modify your [routes configuration](../../define-routes/_index.md).
When you add a new custom domain for a preview environment,
just attach it to the custom production domain it replaces.
If you have multiple custom production domains,
you need to select which one you're replacing.
Example
You have two environments, a production environment and a staging environment.
You’ve added the example.com custom domain to your production environment.
You want to add the staging.example.com custom domain to your staging environment.
To do so, you need to attach the new staging.example.com custom domain
to its corresponding custom production domain example.com.
You can then access your staging environment through staging.example.com,
and still access your production environment through example.com.
If you have multiple custom domains on your production environment,
when you set up a custom domain on a preview environment,
you don't need to update your [routes configuration](../../define-routes/_index.md) either.
Upsun automatically figures out the routing of your preview environment
based on the following elements:
- The custom production domains in your existing [routes configuration](../../define-routes/_index.md)
- The custom domains for preview environments attached to each of those custom production domains
## Before you start
You need:
- A production environment with at least one custom domain already set up
- At least one preview (staging or development) environment
- Optional: The [Upsun CLI](../../administration/cli/_index.md) (v4.8.0+)
To prevent abuse, by default you can add custom domains to up to 5 preview environments per project only.
This limit doesn't include the production environment,
and you can increase it without charge.
To do so, [contact Support](/learn/overview/get-support.md).
Note
If you delete a custom production domain,
all of the attached custom domains for preview environments are deleted too.
You need to rebuild the affected preview environments for the deletion to be complete.
## Add a custom domain to a preview environment
To add a custom domain to a preview environment, follow these steps:
Configure your DNS provider.
In particular, make sure your DNS record points to the target of your preview environment.
Note
Using the target of your production environment to configure your DNS provider is technically possible,
but Upsun recommends using the target of your preview environment as a best practice.
Get the target for your preview environment.
To do so, navigate to your preview environment and click Settings.
Select the Domains tab.
In the Configure your domain section, copy the content of the CNAME record field.
Save it for later use at step 7.
Click Add domain.
Name the custom domain for your preview environment.
Attach the custom domain for your preview environment to the desired production custom domain.
Click Add.
Click Okay.
Configure your DNS provider.
In particular, make sure your DNS record points to the target of your preview environment.
Note
Using the target of your production environment to configure your DNS provider is technically possible,
but Upsun recommends using the target of your preview environment as a best practice.
Note
You can’t update a custom domain when it’s used on a preview environment.
You can only delete it and create a new one as a replacement.
### Example
You've added the `mysite.com` custom domain to your production environment.
You now want to add the `mydev.com` custom domain to a preview environment called `Dev`.
To do so, follow these steps:
upsun domain:add mydev.com --environment Dev --attach mysite.com
Get the target for Dev.
To do so, navigate to Dev and click Settings.
Select the Domains tab.
In the Configure your domain section, copy the content of the CNAME record field.
Save it for later use at step 7.
Click Add domain.
Enter mydev.com as a name for the custom domain you want to add to Dev.
Select mysite.com as the production custom domain you want to attach mydev.com to.
In the above example, the `Dev` environment needs to exist
for you to add the `mydev.com` custom domain successfully.
If the `Dev` environment is later removed,
the `mydev.com` custom domain is removed too.
## List the custom domains of a preview environment
Navigate to your preview environment and click Settings.
Select the Domains tab.
All the custom domains for the selected environment are displayed.
Click More on the custom domain you want to delete.
Click Delete.
Click Yes, delete.
# Content delivery networks (CDNs) [Set up your Cloudflare CDN](https://docs.upsun.com/domains/cdn/cloudflare.html)
You can [use a CDN](./_index.md) to deliver your site's content to users more quickly.
## Before you begin
You need:
- An up-and-running Upsun project
- A [Cloudflare](https://www.cloudflare.com/) CDN subscription
## 1. Avoid double-caching
To avoid stale content that can't be cleared,
avoid using Cloudflare with [HTTP caching](/define-routes/cache.md).
For routes where Cloudflare is used,
disable HTTP caching using the following configuration:
```yaml {configFile="routes"}
https://{default}/:
type: upstream
...
cache:
enabled: false
```
## 2. Set up your Cloudflare CDN
To properly configure your Cloudflare CDN,
see the Cloudflare official documentation on [how to get started](https://developers.cloudflare.com/cache/get-started/).
Then set up a [custom domain](../steps/_index.md).
To get the [DNS challenge to succeed](../troubleshoot.md#ownership-verification),
have your CDN point to your [project's target URL](../../domains/steps/_index.md#1-get-the-target-for-your-project).
## 3. Handle apex domains
To start routing client traffic through Cloudflare,
you need to [create `CNAME` records for your domain names](../../domains/steps/dns.md)
through your DNS provider.
But `CNAME` records can't point to apex domains.
As a workaround, Cloudflare offers [`HTTPS` records](https://developers.cloudflare.com/dns/manage-dns-records/reference/dns-record-types/#svcb-and-https) and [`CNAME` flattening](https://developers.cloudflare.com/dns/additional-options/cname-flattening/).
## 4. Mitigate security risks
Like all networks exposed to the internet, your origin server may become the target of security attacks.
The best way to protect your site from threats like on-path attacks, spoofing attacks, or credential stuffing,
is to [configure mutual TLS (mTLS)](https://community.platform.sh/t/configure-mutual-tls-with-cloudflare-and-platform-sh/761).
[mTLS](https://www.cloudflare.com/en-gb/learning/access-management/what-is-mutual-tls/) not only has both parties in a connection authenticate each other
through the TLS protocol.
It also ensures that requests can't be sent directly to the origin server (Upsun).
Instead, requests must transit through Cloudflare first.
Note
mTLS is only compatible with environments where you have attached domains you own, meaning:
Therefore, mTLS is not compatible with preview environments created by a source code integration.
If you can't use mTLS, you can still take the following measures to protect your site from on-path attacks:
1. [Enable full strict SSL/TLS encryption](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes/full-strict/).
Any communication between a client and Cloudflare or between Cloudflare and your Upsun server is then encrypted through HTTPS.
In addition, Cloudflare checks that your Upsun server's [TLS certificate](/glossary.md#transport-layer-security-tls)
was issued by a trusted certificate authority.
This confirms the client is truly communicating with your Upsun server.
2. [Enable HTTP strict transport security (HSTS)](https://developers.cloudflare.com/ssl/edge-certificates/additional-options/http-strict-transport-security/).
This ensures that your HTTPS connections can't be downgraded to HTTP.
# What is Upsun? [ Get support](https://docs.upsun.com/learn/overview/get-support.html)
Find out how to get help if you’re experiencing issues with Upsun.
## Create a support ticket
If you're experiencing issues related to
the proper functioning of the Upsun infrastructure, application container software, or build processes;
have found possible bugs; or have general questions,
open a support ticket:
1. [Open the Console](https://console.upsun.com/)
2. Click the **Help** dropdown in the upper right-hand corner.
3. Select **Support** from the options in the dropdown.
4. Click **+ New ticket**.
5. Fill in the ticket fields and click **Submit**.
Or use these shortcuts to [access all support tickets](https://console.upsun.com/-/users/~/tickets)
or [open a new ticket](https://console.upsun.com/-/users/~/tickets/open).
Once you submit a ticket, you see it in a list of all tickets created, for all projects you have access to, within your organization.
Note that once you submit the ticket, you can't modify or delete the submission.
If you have any additional information, you can select the submitted ticket and write a message.
## Community
To talk about app development or framework-related questions,
join other customers and engineers in the [Discord](https://discord.gg/PkMc2pVCDV).
Also, the [Upsun Community forum](https://community.platform.sh/) has how-to guides with suggestions
on how to get the most out of Upsun.
## Contact Sales
If you have questions about pricing or need help figuring out if Upsun is the right solution for your team,
get in touch with [Sales](https://upsun.com/register/).
## Delete your account
To permanently delete your Upsun account, follow these steps:
Warning
Deleting your Upsun account automatically deletes your linked Platform.sh account,
as well as any linked Ibexa Cloud, Pimcore PaaS, or Shopware PaaS accounts you may hold.
1. [Open the Console](https://console.upsun.com/).
2. Open the user menu (your name or profile picture) and select **My Profile**.
3. Click **Delete account**.
4. Check that the pre-filled information is correct and click **Submit**.
5. Read the consequences of account deletion and click **Submit request** to confirm.
Your request is now submitted and will be handled by Support shortly.
# Custom domains [Going Live - Troubleshooting](https://docs.upsun.com/domains/troubleshoot.html)
If your site doesn’t resolve after you’ve made DNS changes, check potential solutions to common issues.
## Verify DNS
On the command line using macOS, Linux, or the Windows Subsystem for Linux, run the following command:
```bash
host www.YOUR_DOMAIN
```
If your domain is `example.com`, the response should be something like the following:
```text
www.example.com is an alias for main-abcd123.abcdefgh1234567.eu.platformsh.site
main-abcd123.abcdefgh1234567.eu.platformsh.site has address 192.0.2.1
```
If it isn't, try the following steps:
- Your DNS server might not be correctly configured or the old DNS records are still cached.
Try removing your local DNS cache.
- Set your computer's DNS server to any Public DNS resolver (like [CloudFlare](https://developers.cloudflare.com/1.1.1.1/) or [Google](https://developers.google.com/speed/public-dns/docs/using))
to see if the issue is with the DNS server you are using.
- Run `ping www.YOUR_DOMAIN`.
If the result is different from what you got from running `host www.YOUR_DOMAIN`,
you might need to remove your test settings.
## Verify SSL/TLS encryption
To find out where your domain is pointing to,
you can use [the certificate checker tool](https://certcheck.pltfrm.sh/).
This tool provides guidance on certificates,
including when you use a [CDN](./cdn/_index.md).
Check both the apex and the `www` domains to ensure they both point to your project.
For further investigations, run the following command in a shell:
```bash
curl -I -v https://www.YOUR_DOMAIN
```
Look for error messages.
Often the problem is caused by a mismatch between the certificate and the domain name or an expired [custom certificate](steps/tls.md).
### Error provisioning certificates
When a Let's Encrypt certificate fails to provision after the build hook has completed,
you get output similar to the following:
```bash
Provisioning certificates
Validating 2 new domains
E: Error validating domains: urn:ietf:params:acme:error:rejectedIdentifier :: The server will not issue certificates for the identifier :: NewOrder request did not include a SAN short enough to fit in CN
Unable to validate domains domain a-new-and-really-awesome-feature-abc1234-defghijk56789.eu3.platformsh.site, www.domain a-new-and-really-awesome-feature-abc1234-defghijk56789.eu3.platformsh.site, will retry in the background.
(Next refresh will be at 2023-04-28 02:22:50.639301+00:00.)
E: Error: TLS Certificate provisioning failed
```
The renewal may fail because of the 64-character limit Let's Encrypt places on URLs.
If you have a branch with a long name, the environment URL is over this limit and the certificate is rejected.
To solve this, shorten your branch name so it doesn't exceed 20 characters.
Generated URLs for environments have the following pattern:
```bash
ENVIRONMENT-PROJECT_ID.REGION.platformsh.site
```
If you have a [default domain](../define-routes/_index.md#default) set up, the generated URL has the following pattern:
```bash
YOUR_DOMAIN.ENVIRONMENT-PROJECT_ID.REGION.platformsh.site
```
The generated URLs consist of:
- `YOUR_DOMAIN` = the amount of characters your domain has
- `ENVIRONMENT` = `BRANCH_NAME` + 7 character hash
- `PROJECT_ID` = 13 characters
- `REGION` = 2 to 4 characters, depending on the region
- `platformsh.site` = 15 characters
- extra characters like `.` and `-` = 4 to 5 characters, depending on if you have a default domain
This leaves you with 21 to 23 characters for your branch name (`BRANCH_NAME`) without exceeding the 64-character limit,
depending on the region.
To ensure your renewals succeed,
keep your branch names under 20 characters.
### Ownership verification
To provide a valid TLS-certificate,
the certificate issuer checks that the requester is entitled to receive the requested certificate.
This check is known as the _Challenge_ step.
The certificate request is generated based on your [routes definition](../define-routes/_index.md).
If you want your site to be available with `example.com` and its `www.example.com` subdomain, make sure both are defined in your routes.
To pass this verification, there are requirements you need to meet.
Upsun checks that all the routes you defined are pointing to your project.
For the challenge to complete,
domains and subdomains must point directly to your Upsun project.
Otherwise, you get an error similar to:
E: Error validating domain www.example.com: Couldn't complete challenge [HTTP01: pending | DNS01: pending | TLSALPN01: pending]
Unable to validate domains www.example.com, will retry in the background.
When you use a CDN, to ensure the challenge succeeds, check that:
The /.well-known/ route,
as in https://www.example.com/.well-known/, is accessible with no redirects
If you don’t follow those requirements, you get an error message similar to:
W: Failed to verify the challenge at the gateway for the domain 'www.example.com'
E: Error validating domain www.example.com: Couldn't complete challenge [HTTP01: The client lacks sufficient authorization]
For more information, see how to setup your CDN.
For more details regarding the challenge step, consult your certificate issuer’s documentation.
A common issuer is Let’s Encrypt.
Make sure that the [apex domain](/glossary.md#apex-domain) and its `www` subdomain are both pointing where needed.
Note that it can take up to 72 hours for DNS changes to be effective.
For more information, see how to [set up a custom domain](../domains/steps/_index.md).
If the changes take longer than expected,
[redeploy](../development/troubleshoot.md#force-a-redeploy) the impacted environment.
Also make sure that no conflicting DNS records exist for your domain.
For example, a conflicting AAAA (IPv6) DNS record can result in a `[HTTP01: The client lacks sufficient authorization]` error.
If the certificate generation issue persists,
check if an outage is ongoing with your certificate issuer (the most common one is [Let's Encrypt](https://letsencrypt.status.io/))
and with your CDN provider if you have one.
If not, [contact Support](/learn/overview/get-support.md).
### Check your routes configuration
Certificates are generated based on your [routes configuration](../define-routes/_index.md).
When a certificate is renewed, the renewal bot checks that all of the defined routes can be accessed.
If at least one of the routes defined in your `.upsun/config.yaml` file can't be accessed,
the renewal fails and the following error is displayed:
```
Provisioning certificates
Validating 2 new domains
W: Failed to verify the challenge at the gateway for the domain 'www.example.com'
E: Error validating domain www.example.com: Couldn't complete challenge [HTTP01: There was a problem with a DNS query during identifier validation]
Unable to validate domains www.example.com, will retry in the background.
(Next refresh will be at 2023-07-04 17:43:10.259891+00:00.)
Certificates
- certificate 61bc4c8: expiring on 2023-09-02 01:11:12+00:00, covering sdgs.un.org
E: Error: TLS Certificate provisioning failed
```
For example, if you add `example.com` and `www.example.com` to your routes configuration
but the `www` subdomain doesn't point to your project through [a `CNAME` record](./steps/dns.md#cname-records),
the certificate renewal fails.
For the renewal to succeed, add the missing `CNAME` record to your DNS
or remove `www.example.com` (and any other `www` route) from your `.upsun/config.yaml` file.
## Verify your application
Check your app's logs and look for anomalies.
On the command line type `upsun logs app` and `upsun logs error`.
## Use ASCII for the domain
Upsun expects an ASCII representation of your domain.
To use an internationalized domain name (IDN), convert it to ASCII.
Use a tool such as the [conversion tool provided by Verisign](https://www.verisign.com/en_US/channel-resources/domain-registry-products/idn/idn-conversion-tool/index.xhtml).
## Something still wrong?
For more general information, see how to [troubleshoot development](/development/troubleshoot).
If your website is still not working as expected, [contact support](/learn/overview/get-support.md).
# Administration [Multi-Factor Authentication (MFA)](https://docs.upsun.com/administration/mfa.html)
Multi-Factor Authentication (MFA) enhances security by protecting both your organization and every user account that interacts with it
through SSH or the Upsun API.
When MFA is enforced within an organization, every project contributor **must** enable MFA on their user account so they can run Git commands,
SSH into an environment, or trigger actions through the Upsun API.
## Enable MFA on your user account
To access an organization that enforces MFA or any of its projects,
you **must** enable MFA on your user account.
Failure to do so results in forbidden access to the organization from the Console or API,
and an [error message](/development/ssh/troubleshoot-ssh.md#mfa-related-error-message) when trying to SSH into its environments.
To enable MFA on your user account, follow these steps:
1. In the Console, open the user menu (your name or profile picture).
2. Click **My profile**
3. Click **Security**.
4. Click **Set up application**.
5. Follow the instructions for the chosen authentication app.
6. Click **Verify & save**.
7. Refresh your SSH credentials by running `upsun login -f` in the CLI.
## Enforce MFA within your organization
Only organization owners and admin users can enable MFA within an organization.
However, even if you have the required permissions,
you mustenable MFA on your user account prior to enforcing it within the whole organization.
To enable MFA within your organization, follow these steps:
1. In the Console, open the user menu (your name or profile picture).
2. Click **Settings**.
3. Click **Security**.
4. In the **MFA required** area, set the **Enable** toggle on.
### Send email reminders
You can send email reminders to users who haven't enabled MFA on their user account yet.
To do so, follow these steps:
1. In the Console, open the user menu (your name or profile picture).
2. Click **Settings**.
3. Click **Security**.
4. In the **User security settings** area, find the user you want to send a reminder to.
5. Click ** More** next to that user.
6. Select **Remind**.
An email is sent to the user with instructions on how to enable MFA on their user account.
Note
You can send reminders to multiple users at once.
To do so, in the User security settings user list,
select the desired users by checking the boxes in front of their names.
Click Remind at the top of the list to trigger the reminder emails.
# App reference [Single-runtime image](https://docs.upsun.com/create-apps/app-reference/single-runtime-image.html)
See all of the options for controlling your apps and how they’re built and deployed on Upsun.
Configuration is all done in a `.upsun/config.yaml` file,
located at the root of your Git repository.
See a [comprehensive example](../_index.md#comprehensive-example) of a configuration in
a `.upsun/config.yaml` file.
## Primary application properties
All application configuration takes place in a `.upsun/config.yaml` file, with each application configured
under a unique key beneath the top-level `applications` key.
For example, it is possible to deploy two application containers - one JavaScript and the other Python - for the
frontend and backend components of a deployed site.
In this case, the unified `.upsun/config.yaml` file would look like:
```yaml {configFile="app"}
applications:
frontend:
type: 'nodejs:22'
# Additional frontend configuration
backend:
type: 'python:3.9'
# Additional backend configuration
```
The following table presents all properties available at the level just below the unique application name (`frontend`
and `backend` above).
The column _Set in instance?_ defines whether the given property can be overridden within a `web` or `workers` instance.
To override any part of a property, you have to provide the entire property.
| Name | Type | Required | Set in instance? | Description |
|--------------------|-----------------------------------------------------|----------|------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `type` | A [type](#types) | Yes | No | The base image to use with a specific app language. Format: `runtime:version`. |
| `relationships` | A dictionary of [relationships](#relationships) | | Yes | Connections to other services and apps. |
| `mounts` | A dictionary of [mounts](#mounts) | | Yes | Directories that are writable even after the app is built. Allocated disk for mounts is defined with a separate resource configuration call using `upsun resources:set`. |
| `web` | A [web instance](#web) | | N/A | How the web application is served. |
| `workers` | A [worker instance](#workers) | | N/A | Alternate copies of the application to run as background processes. |
| `timezone` | `string` | | No | The timezone for crons to run. Format: a [TZ database name](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). Defaults to `UTC`, which is the timezone used for all logs no matter the value here. See also [app runtime timezones](../timezone.md) |
| `access` | An [access dictionary](#access) | | Yes | Access control for roles accessing app environments. |
| `variables` | A [variables dictionary](#variables) | | Yes | Variables to control the environment. |
| `firewall` | A [firewall dictionary](#firewall) | | Yes | Outbound firewall rules for the application. |
| `build` | A [build dictionary](#build) | | No | What happens when the app is built. |
| `dependencies` | A [dependencies dictionary](#dependencies) | | No | What global dependencies to install before the `build` hook is run. |
| `hooks` | A [hooks dictionary](#hooks) | | No | What commands run at different stages in the build and deploy process. |
| `crons` | A [cron dictionary](#crons) | | No | Scheduled tasks for the app. |
| `source` | A [source dictionary](#source) | | No | Information on the app's source code and operations that can be run on it. |
| `runtime` | A [runtime dictionary](#runtime) | | No | Customizations to your PHP or Lisp runtime. |
| `additional_hosts` | An [additional hosts dictionary](#additional-hosts) | | Yes | Maps of hostnames to IP addresses. |
## Root directory
Some of the properties you can define are relative to your app's root directory.
The root defaults to the root of the repository.
```yaml {configFile="app"}
applications:
frontend:
type: 'nodejs:22'
# Default behavior of source.root
source:
root: "/"
```
That is, if a custom value for `source.root` is not provided in your configuration, the default behavior is equivalent
to the above.
To specify another directory, for example for a [multi-app project](../multi-app/_index.md),
use the [`source.root` property](#source).
## Types
Note
You can now use the Upsun composable image (BETA) to install runtimes and tools in your application container.
If you’ve reached this section from another page, you may be interested in supported stacks where type was referenced.
See supported Nix packages for the stack key for more information.
The `type` defines the base container image used to run the application.
The version is the major (`X`) and sometimes minor (`X.Y`) version numbers,
depending on the service, as in the following table.
Security and other patches are taken care of for you automatically.
Available languages and their supported versions:
Heads up!
The file registry/images/tables/runtimes_supported.md was not found. Did you define it in docs/data/remote-examples to be downloaded?
### Example configuration
These are used in the format `runtime:version`:
```yaml {configFile="app"}
applications:
myapp:
type: 'php:8.4'
```
### Mix of images
In a [multiple application context](/create-apps/multi-app/_index.md), you can mix both [single-runtime image](/create-apps/app-reference/single-runtime-image.md) and [Composable Image (BETA)](/create-apps/app-reference/composable-image.md) per application.
As an example configuration for a ``frontend`` and a ``backend`` application:
```yaml {configFile="app"}
applications:
backend:
type: 'nodejs:22
frontend:
stack:
- "php@8.4":
extensions:
- apcu
- sodium
- xsl
- pdo_sqlite
- "python@3.12"
- "python312Packages.yq" # python package specific
```
## Resources
Resources for application containers are not committed to YAML files, but instead managed over the API using either the
Console or the `upsun resources:set` command.
For more information, see how to [manage resources](/manage-resources.md).
## Relationships
To allow containers in your project to communicate with one another,
you need to define relationships between them.
You can define a relationship between an app and a service, or [between two apps](/create-apps/multi-app/relationships.md).
The quickest way to define a relationship between your app and a service
is to use the service's default endpoint.
However, some services allow you to define multiple databases, cores, and/or permissions.
In these cases, you can't rely on default endpoints.
Instead, you can explicitly define multiple endpoints when setting up your relationships.
Note
App containers don’t have a default endpoint like services.
To connect your app to another app in your project,
you need to explicitly define the http endpoint as the endpoint to connect both apps.
For more information, see how to define relationships between your apps.
Availability
New syntax (default and explicit endpoints) described below is supported by most, but not all, image types
(Relationship 'SERVICE_NAME' of application 'app' ... targets a service without a valid default endpoint configuration.).
This syntax is currently being rolled out for all images.
If you encounter this error, use the “legacy” Upsun configuration noted at the bottom of this section.
To define a relationship between your app and a service:
The SERVICE_NAME is the name of the service as defined in its configuration.
It is used as the relationship name, and associated with a null value.
This instructs Upsun to use the service’s default endpoint to connect your app to the service.
For example, if you define the following configuration:
.upsun/config.yaml
applications:APP_NAME:# ...relationships:mariadb:
Upsun looks for a service named mariadb in your .upsun/config.yaml file,
and connects your app to it through the service’s default endpoint.
For reference, the equivalent configuration using explicit endpoints would be the following:
RELATIONSHIP_NAME is the name you want to give to the relationship.
SERVICE_NAME is the name of the service as defined in its configuration.
ENDPOINT_NAME is the endpoint your app will use to connect to the service (refer to the service reference to know which value to use).
For example, to define a relationship named database that connects your app to a service called mariadb through the db1 endpoint,
use the following configuration:
.upsun/config.yaml
applications:APP_NAME:# ...relationships:database:# The name of the relationship.service:mariadbendpoint:db1
For more information on how to handle multiple databases, multiple cores,
and/or different permissions with services that support such features,
see each service’s dedicated page:
Feel free to use this until the default and explicit endpoint syntax is supported on all images.
## Available disk space
Disk for application containers are not committed to YAML files, but instead managed over the API using either the
Console or the `upsun resources:set` command.
For more information, see how to [manage resources](/manage-resources.md).
### Downsize a disk
You can decrease the size of an existing disk for an app. If you do so, be aware that:
- Backups from before the downsize are incompatible and can no longer be used. You need to [create new backups](/environments/backup).
- The downsize fails if there’s more data on the disk than the desired size.
## Mounts
After your app is built, its file system is read-only.
To make changes to your app's code, you need to use Git.
For enhanced flexibility, Upsun allows you to define and use writable directories called "mounts".
Mounts give you write access to files generated by your app (such as cache and log files)
and uploaded files without going through Git.
When you define a mount, you are mounting an external directory to your app container,
much like you would plug a hard drive into your computer to transfer data.
### Define a mount
To define a mount, use the following configuration:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: nodejs:22
mounts:
'MOUNT_PATH':
source: MOUNT_TYPE
source_path: SOURCE_PATH_LOCATION
```
MOUNT_PATH is the path to your mount **within the app container** (relative to the app's root).
If you already have a directory with that name, you get a warning that it isn't accessible after the build.
See how to [troubleshoot the warning](../troubleshoot-mounts.md#overlapping-folders).
| Name | Type | Required | Description |
| ------------- | -------------------- | -------- | ----------- |
| `source` | `storage`, `instance`, `tmp` (also called `temporary`), or `service` | Yes | Specifies the type of the mount:
- By design, `storage` mounts can be shared between instances of the same app. You can also configure them so they are [shared between different apps](#share-a-mount-between-several-apps).
-`instance` mounts are local mounts. Unique to your app, they are useful to store files that remain local to the app instance, such as application logs.
- `tmp` (or `temporary`) mounts are local ephemeral mounts, where an external directory is mounted to the `/tmp` directory of your app. The content of a `tmp` mount **may be removed during infrastructure maintenance operations**. Therefore, `tmp` mounts allow you to **store files that you’re not afraid to lose**, such as your application cache that can be seamlessly rebuilt. Note that the `/tmp` directory has **a maximum allocation of 8 GB**.
- `service` mounts can be useful if you want to explicitly define and use a [Network Storage](/add-services/network-storage.md) service to share data between different apps (instead of using a `storage` mount).|
| `source_path` | `string` | No | Specifies where the mount points **inside the [external directory](#mounts)**.
- If you explicitly set a `source_path`, your mount points to a specific subdirectory in the external directory.
- If the `source_path` is an empty string (`""`), your mount points to the entire external directory.
- If you don't define a `source_path`, Upsun uses the MOUNT_PATH as default value, without leading or trailing slashes.For example, if your mount lives in the `/web/uploads/` directory in your app container, it will point to a directory named `web/uploads` in the external directory. **WARNING:** Changing the name of your mount affects the `source_path` when it's undefined. See [how to ensure continuity](#ensure-continuity-when-changing-the-name-of-your-mount) and maintain access to your files. |
| `service` | `string` | | The purpose of the `service` key depends on your use case. In a multi-app context where a `storage` mount is shared between apps, `service` is required. Its value is the name of the app whose mount you want to share. See how to [share a mount between several apps](#share-a-mount-between-several-apps). In a multi-app context where a [Network Storage service](/add-services/network-storage.md) (`service` mount) is shared between apps, `service` is required and specifies the name of that Network Storage. |
The accessibility to the web of a mounted directory depends on the [`web.locations` configuration](#web).
Files can be all public, all private, or with different rules for different paths and file types.
Note that when you remove a `tmp` mount from your `.upsun/config.yaml` file,
the mounted directory isn't deleted.
The files still exist on disk until manually removed,
or until the app container is moved to another host during a maintenance operation.
### Example configuration
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: nodejs:20
mounts:
'web/uploads':
source: storage
source_path: uploads
'/.tmp_platformsh':
source: tmp
source_path: files/.tmp_platformsh
'/build':
source: storage
source_path: files/build
'/.cache':
source: tmp
source_path: files/.cache
'/node_modules/.cache':
source: tmp
source_path: files/node_modules/.cache
```
### Ensure continuity when changing the name of your mount
Changing the name of your mount affects the default `source_path`.
Say you have a `/my/cache/` mount with an undefined `source_path`:
```yaml {configFile="app"}
applications:
myapp:
mounts:
'/my/cache/':
source: tmp
```
If you rename the mount to `/cache/files/`, it will point to a new, empty `/cache/files/` directory.
To ensure continuity, you need to explicitly define the `source_path` as the previous name of the mount, without leading
or trailing slashes:
```yaml {configFile="app"}
applications:
myapp:
mounts:
'/cache/files/':
source: tmp
source_path: my/cache
```
The `/cache/files/` mount will point to the original `/my/cache/` directory, maintaining access to all your existing
files in that directory.
### Share a mount between several apps
By design, [`storage` mounts](#mounts) are shared **between different instances of the same app**,
which enables [horizontal scaling](/manage-resources/_index.md).
In a [multi-application context](/create-apps/multi-app/_index.md),
you can even share a `storage` mount **between different applications** in the same project.
To do so, you need to define a `storage` mount in each of your app containers,
and point each of those mounts to the same shared external network directory.
Use the following configuration:
```yaml {configFile="app"}
applications:
app1:
mounts:
'MOUNT_PATH_1':
source: storage
source_path: SOURCE_PATH_LOCATION
app2:
mounts:
'MOUNT_PATH_2':
source: storage
service: app1
source_path: SOURCE_PATH_LOCATION
```
- MOUNT_PATH_1 and MOUNT_PATH_2 are the paths to each mount **within their
respective app container** (relative to the app's root).
- When configuring the first `storage` mount, you don't need to include the `service` key.
The first mount implicitly points to an external network directory.
The `service` key is required for subsequent mounts, to ensure they use the same external network directory as the
first mount.
- The `source_path` allows you to point each mount to the same subdirectory **within the shared external network
directory**.
Example
You have a backend app and a frontend app.
You want both apps to share data from the same mount.
Follow these steps:
In your backend app configuration, define a storage mount:
.upsun/config.yaml
applications:backend:mounts:var/uploads:#The path to your mount within the backend app container.source:storagesource_path:backend/uploads#The path to the source of the mount within the external network directory.
This creates a storage mount named var/uploads in the backend app container.
The mount points to the backend/uploads directory within an external network directory.
In your frontend app configuration, define another storage mount:
.upsun/config.yaml
applications:applications:backend:mounts:var/uploads:source:storagesource_path:backend/uploadsfrontend:mounts:web/uploads:#The path to your mount within the frontend app container.source:storageservice:backend#The name of the other app, so the mount can point to the same external network directory as that other app's mount.source_path:backend/uploads#The path to the source of the mount within the shared external network directory.
This creates another storage mount named web/uploads in the frontend app container.
The service key allows you to specify that the web/uploads mount should use the same external network directory
as the mount previously defined in the backend app container.
The source_path key specifies which subdirectory within the external network directory both mounts should share (
here, the backend/uploads directory).
Note that another way to share data between apps through a mount is by
explicitly [defining a Network Storage service](/add-services/network-storage.md).
### Overlapping mounts
The locations of mounts as they are visible to application containers can overlap somewhat.
For example:
```yaml {configFile="app"}
applications:
myapp:
# ...
mounts:
'var/cache_a':
source: storage
source_path: cacheA
'var/cache_b':
source: tmp
source_path: cacheB
'var/cache_c':
source: instance
source_path: cacheC
```
In this case, it does not matter that each mount is of a different `source` type.
Each mount is restricted to a subfolder within `var`, and all is well.
The following, however, is not allowed and will result in a failure:
```yaml {configFile="app"}
applications:
myapp:
# ...
mounts:
'var/':
source: storage
source_path: cacheA
'var/cache_b':
source: tmp
source_path: cacheB
'var/cache_c':
source: instance
source_path: cacheC
```
The `storage` mount type specifically exists to share data between instances of the same application, whereas `tmp` and `instance` are meant to restrict data to build time and runtime of a single application instance, respectively.
These allowances are not compatible, and will result in an error if pushed.
## Web
Use the `web` key to configure the web server running in front of your app.
Defaults may vary with a different [image `type`](#types).
| Name | Type | Required | Description |
|-------------|--------------------------------------------|-------------------------------|------------------------------------------------------|
| `commands` | A [web commands dictionary](#web-commands) | See [note](#required-command) | The command to launch your app. |
| `upstream` | An [upstream dictionary](#upstream) | | How the front server connects to your app. |
| `locations` | A [locations dictionary](#locations) | | How the app container responds to incoming requests. |
See some [examples of how to configure what's served](../web/_index.md).
### Web commands
| Name | Type | Required | Description |
|-------------|----------|-------------------------------|-----------------------------------------------------------------------------------------------------|
| `pre_start` | `string` | | Command run just prior to `start`, which can be useful when you need to run _per-instance_ actions. |
| `start` | `string` | See [note](#required-command) | The command to launch your app. If it terminates, it's restarted immediately. |
Example:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'python:3.9'
web:
commands:
start: 'uwsgi --ini conf/server.ini'
```
This command runs every time your app is restarted, regardless of whether or not new code is deployed.
Note
Never “background” a start process using &.
That’s interpreted as the command terminating and the supervisor process starts a second copy,
creating an infinite loop until the container crashes.
Just run it as normal and allow the Upsun supervisor to manage it.
#### Required command
On all containers other than PHP, the value for `start` should be treated as required.
On PHP containers, it's optional and defaults to starting PHP-FPM (`/usr/bin/start-php-app`).
It can also be set explicitly on a PHP container to run a dedicated process,
such as [React PHP](https://github.com/platformsh-examples/platformsh-example-reactphp)
or [Amp](https://github.com/platformsh-examples/platformsh-example-amphp).
See how to set up [alternate start commands on PHP](/languages/php/_index.md#alternate-start-commands).
### Upstream
| Name | Type | Required | Description | Default |
|-----------------|---------------------|----------|-------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------|
| `socket_family` | `tcp` or `unix` | | Whether your app listens on a Unix or TCP socket. | Defaults to `tcp` for all [image types](#types) except PHP; for PHP image types the default is `unix`. |
| `protocol` | `http` or `fastcgi` | | Whether your app receives incoming requests over HTTP or FastCGI. | Default varies based on [image `type`](#types). |
For PHP, the defaults are configured for PHP-FPM and shouldn't need adjustment.
For all other containers, the default for `protocol` is `http`.
The following example is the default on non-PHP containers:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'python:3.9'
web:
upstream:
socket_family: tcp
protocol: http
```
#### Where to listen
Where to listen depends on your setting for `web.upstream.socket_family` (defaults to `tcp`).
| `socket_family` | Where to listen |
|-----------------|---------------------------------------------------------------------------------------------------------------------------------------|
| `tcp` | The port specified by the [`PORT` environment variable](/development/variables/use-variables.md#use-provided-variables) |
| `unix` | The Unix socket file specified by the [`SOCKET` environment variable](/development/variables/use-variables.md#use-provided-variables) |
If your application isn't listening at the same place that the runtime is sending requests,
you see `502 Bad Gateway` errors when you try to connect to your website.
### Locations
Each key in the `locations` dictionary is a path on your site with a leading `/`.
For `example.com`, a `/` matches `example.com/` and `/admin` matches `example.com/admin`.
When multiple keys match an incoming request, the most-specific applies.
The following table presents possible properties for each location:
| Name | Type | Default | Description |
|---------------------|------------------------------------------------------|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `root` | `string` | | The directory to serve static assets for this location relative to the [app's root directory](#root-directory). Must be an actual directory inside the root directory. |
| `passthru` | `boolean` or `string` | `false` | Whether to forward disallowed and missing resources from this location to the app. A string is a path with a leading `/` to the controller, such as `/index.php`.
If your app is in PHP, when setting `passthru` to `true`, you might want to set `scripts` to `false` for enhanced security. This prevents PHP scripts from being executed from the specified location. You might also want to set `allow` to `false` so that not only PHP scripts can't be executed, but their source code also can't be delivered. |
| `index` | Array of `string`s or `null` | | Files to consider when serving a request for a directory. When set, requires access to the files through the `allow` or `rules` keys. |
| `expires` | `string` | `-1` | How long static assets are cached. The default means no caching. Setting it to a value enables the `Cache-Control` and `Expires` headers. Times can be suffixed with `ms` = milliseconds, `s` = seconds, `m` = minutes, `h` = hours, `d` = days, `w` = weeks, `M` = months/30d, or `y` = years/365d. If a `Cache-Control` appears on the `headers` configuration, `expires`, if set, will be ignored. Thus, make sure to set the `Cache-Control`'s `max-age` value when specifying a the header. |
| `allow` | `boolean` | `true` | Whether to allow serving files which don't match a rule. |
| `scripts` | `boolean` | | Whether to allow scripts to run. Doesn't apply to paths specified in `passthru`. Meaningful only on PHP containers. |
| `headers` | A headers dictionary | | Any additional headers to apply to static assets, mapping header names to values. Responses from the app aren't affected. |
| `request_buffering` | A [request buffering dictionary](#request-buffering) | See below | Handling for chunked requests. |
| `rules` | A [rules dictionary](#rules) | | Specific overrides for specific locations. |
#### Rules
The rules dictionary can override most other keys according to a regular expression.
The key of each item is a regular expression to match paths exactly.
If an incoming request matches the rule, it's handled by the properties under the rule,
overriding any conflicting rules from the rest of the `locations` dictionary.
Under `rules`, you can set all of the other possible [`locations` properties](#locations)
except `root`, `index` and `request_buffering`.
In the following example, the `allow` key disallows requests for static files anywhere in the site.
This is overridden by a rule that explicitly allows common image file formats.
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'python:3.9'
web:
locations:
'/':
# Handle dynamic requests
root: 'public'
passthru: '/index.php'
# Disallow static files
allow: false
rules:
# Allow common image files only.
'\.(jpe?g|png|gif|svgz?|css|js|map|ico|bmp|eot|woff2?|otf|ttf)$':
allow: true
```
#### Request buffering
Request buffering is enabled by default to handle chunked requests as most app servers don't support them.
The following table shows the keys in the `request_buffering` dictionary:
| Name | Type | Required | Default | Description |
|--------------------|-----------|----------|---------|-------------------------------------------|
| `enabled` | `boolean` | Yes | `true` | Whether request buffering is enabled. |
| `max_request_size` | `string` | | `250m` | The maximum size to allow in one request. |
The default configuration would look like this:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'python:3.9'
web:
locations:
'/':
passthru: true
request_buffering:
enabled: true
max_request_size: 250m
```
## Workers
Workers are exact copies of the code and compilation output as a `web` instance after a [`build` hook](#hooks).
They use the same container image.
Workers can't accept public requests and so are suitable only for background tasks.
If they exit, they're automatically restarted.
The keys of the `workers` definition are the names of the workers.
You can then define how each worker differs from the `web` instance using
the [top-level properties](#primary-application-properties).
Each worker can differ from the `web` instance in all properties _except_ for:
- `build` and `dependencies` properties, which must be the same
- `crons` as cron jobs don't run on workers
- `hooks` as the `build` hook must be the same
and the `deploy` and `post_deploy` hooks don't run on workers.
A worker named `queue` that was small and had a different start command could look like this:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'python:3.9'
workers:
queue:
commands:
start: |
./worker.sh
```
Workers require resource definition using `upsun resources:set`, same as application containers.
For more information, see how to [manage resources](/manage-resources.md).
## Access
The `access` dictionary has one allowed key:
| Name | Allowed values | Default | Description |
|-------|-------------------------------------|---------------|-----------------------------------------------------------------------|
| `ssh` | `admin`, `contributor`, or `viewer` | `contributor` | Defines the minimum role required to access app environments via SSH. |
In the following example, only users with `admin` permissions for the
given [environment type](/administration/users.md#environment-type-roles)
can access the deployed environment via SSH:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'python:3.9'
access:
ssh: admin
```
## Variables
Upsun provides a number of ways to set [variables](/development/variables/_index.md).
Variables set in your app configuration have the lowest precedence,
meaning they're overridden by any conflicting values provided elsewhere.
All variables set in your app configuration must have a prefix.
Some [prefixes have specific meanings](/development/variables/_index.md#variable-prefixes).
Variables with the prefix `env` are available as a separate environment variable.
All other variables are available in
the [`PLATFORM_VARIABLES` environment variable](/development/variables/use-variables.md#use-provided-variables).
The following example sets two variables:
- A variable named `env:AUTHOR` with the value `Juan` that's available in the environment as `AUTHOR`
- A variable named `d8config:system.site:name` with the value `My site rocks`
that's available in the `PLATFORM_VARIABLES` environment variable
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'python:3.9'
variables:
env:
AUTHOR: 'Juan'
d8config:
"system.site:name": 'My site rocks'
```
You can also define and access more [complex values](/development/variables/use-variables.md#access-complex-values).
## Firewall
Set limits in outbound traffic from your app with no impact on inbound requests.
The `outbound` key is required and contains one or more rules.
The rules define what traffic is allowed; anything unspecified is blocked.
Each rule has the following properties where at least one is required and `ips` and `domains` can't be specified
together:
| Name | Type | Default | Description |
|-----------|---------------------|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `ips` | Array of `string`s | `["0.0.0.0/0"]` | IP addresses in [CIDR notation](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing). See a [CIDR format converter](https://www.ipaddressguide.com/cidr). |
| `domains` | Array of `string`s | | [Fully qualified domain names](https://en.wikipedia.org/wiki/Fully_qualified_domain_name) to specify specific destinations by hostname. |
| `ports` | Array of `integer`s | | Ports from 1 to 65535 that are allowed. If any ports are specified, all unspecified ports are blocked. If no ports are specified, all ports are allowed. Port `25`, the SMTP port for sending email, is always blocked. |
The default settings would look like this:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'python:3.9'
firewall:
outbound:
- ips: [ "0.0.0.0/0" ]
```
### Support for rules
Where outbound rules for firewalls are supported in all environments.
### Multiple rules
Multiple firewall rules can be specified.
In such cases, a given outbound request is allowed if it matches _any_ of the defined rules.
So in the following example requests to any IP on port 80 are allowed
and requests to 1.2.3.4 on either port 80 or 443 are allowed:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'python:3.9'
firewall:
outbound:
- ips: [ "1.2.3.4/32" ]
ports: [ 443 ]
- ports: [ 80 ]
```
### Outbound traffic to CDNs
Be aware that many services are behind a content delivery network (CDN).
For most CDNs, routing is done via domain name, not IP address,
so thousands of domain names may share the same public IP addresses at the CDN.
If you allow the IP address of a CDN, you are usually allowing many or all of the other customers hosted behind that
CDN.
### Outbound traffic by domain
You can filter outbound traffic by domain.
Using domains in your rules rather than IP addresses is generally more specific and secure.
For example, if you use an IP address for a service with a CDN,
you have to allow the IP address for the CDN.
This means that you allow potentially hundreds or thousands of other servers also using the CDN.
An example rule filtering by domain:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'python:3.9'
firewall:
outbound:
- protocol: tcp
domains: [ "api.stripe.com", "api.twilio.com" ]
ports: [ 80, 443 ]
- protocol: tcp
ips: [ "1.2.3.4/29","2.3.4.5" ]
ports: [ 22 ]
```
#### Determine which domains to allow
To determine which domains to include in your filtering rules,
find the domains your site has requested the DNS to resolve.
Run the following command to parse your server’s `dns.log` file
and display all Fully Qualified Domain Names that have been requested:
```bash
awk '/query\[[^P]\]/ { print $6 | "sort -u" }' /var/log/dns.log
```
The output includes all DNS requests that were made, including those blocked by your filtering rules.
It doesn't include any requests made using an IP address.
Example output:
```bash
facebook.com
fastly.com
upsun.com
www.google.com
www.upsun.com
```
## Build
The only property of the `build` dictionary is `flavor`, which specifies a default set of build tasks to run.
Flavors are language-specific.
See what the build flavor is for your language:
- [Node.js](/languages/nodejs/_index.md#dependencies)
- [PHP](/languages/php/_index.md#dependencies)
In all languages, you can also specify a flavor of `none` to take no action at all
(which is the default for any language other than PHP and Node.js).
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'nodejs:22'
build:
flavor: none
```
## Dependencies
Installs global dependencies as part of the build process.
They're independent of your app's dependencies
and are available in the `PATH` during the build process and in the runtime environment.
They're installed before the `build` hook runs using a package manager for the language.
| Language | Key name | Package manager |
|----------|-----------------------|--------------------------------------------------------------------------------------------------------------------|
| PHP | `php` | [Composer](https://getcomposer.org/) |
| Python 2 | `python` or `python2` | [Pip 2](https://packaging.python.org/tutorials/installing-packages/) |
| Python 3 | `python3` | [Pip 3](https://packaging.python.org/tutorials/installing-packages/) |
| Ruby | `ruby` | [Bundler](https://bundler.io/) |
| Node.js | `nodejs` | [npm](https://www.npmjs.com/) (see [how to use yarn](/languages/nodejs/_index.md#use-yarn-as-a-package-manager)) |
| Java | `java` | [Apache Maven](https://maven.apache.org/), [Gradle](https://gradle.org/), or [Apache Ant](https://ant.apache.org/) |
The format for package names and version constraints are defined by the specific package manager.
An example of dependencies in multiple languages:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'nodejs:22'
dependencies:
php: # Specify one Composer package per line.
drush/drush: '8.0.0'
composer/composer: '^2'
python2: # Specify one Python 2 package per line.
behave: '*'
requests: '*'
python3: # Specify one Python 3 package per line.
numpy: '*'
ruby: # Specify one Bundler package per line.
sass: '3.4.7'
nodejs: # Specify one NPM package per line.
pm2: '^4.5.0'
```
## Hooks
There are three different hooks that run as part of the process of building and deploying your app.
These are places where you can run custom scripts.
They are: the `build` hook, the `deploy` hook, and the `post_deploy` hook.
Only the `build` hook is run for [worker instances](#workers), while [web instances](#web) run all three.
The process is ordered as:
1. Variables accessible at build time become available.
1. [Build flavor](#build) runs if applicable.
1. Any [dependencies](#dependencies) are installed.
1. The `build` hook is run.
1. The file system is changed to read only (except for any [mounts](#mounts)).
1. The app container starts. Variables accessible at runtime and services become available.
1. The `deploy` hook is run.
1. The app container begins accepting requests.
1. The `post_deploy` hook is run.
Note that if an environment changes by no code changes, only the last step is run.
If you want the entire process to run, see how
to [manually trigger builds](/development/troubleshoot.md#manually-trigger-builds).
### Writable directories during build
During the `build` hook, there are three writeable directories:
- `PLATFORM_APP_DIR`:
Where your code is checked out and the working directory when the `build` hook starts.
Becomes the app that gets deployed.
- `PLATFORM_CACHE_DIR`:
Persists between builds, but isn't deployed.
Shared by all builds on all branches.
- `/tmp`:
Isn't deployed and is wiped between each build.
Note that `PLATFORM_CACHE_DIR` is mapped to `/tmp`
and together they offer about 8GB of free space.
### Hook failure
Each hook is executed as a single script, so they're considered to have failed only if the final command in them fails.
To cause them to fail on the first failed command, add `set -e` to the beginning of the hook.
If a `build` hook fails for any reason, the build is aborted and the deploy doesn't happen.
Note that this only works for `build` hooks --
if other hooks fail, the app is still deployed.
#### Automated testing
It’s preferable that you set up and run automated tests in a dedicated CI/CD tool.
Relying on Upsun hooks for such tasks can prove difficult.
During the `build` hook, you can halt the deployment on a test failure but the following limitations apply:
- Access to services such as databases, Redis, Vault KMS, and even writable mounts is disabled.
So any testing that relies on it is sure to fail.
- If you haven’t made changes to your app, an existing build image is reused and the build hook isn’t run.
- Test results are written into your app container, so they might get exposed to a third party.
During the `deploy` hook, you can access services but **you can’t halt the deployment based on a test failure**.
Note that there are other downsides:
- Your app container is read-only during the deploy hook,
so if your tests need to write reports and other information, you need to create a file mount for them.
- Your app can only be deployed once the deploy hook has been completed.
Therefore, running automated testing via the deploy hook generates slower deployments.
- Your environment isn’t available externally during the deploy hook.
Unit and integration testing might work without the environment being available,
but you can’t typically perform end-to-end testing until after the environment is up and available.
## Crons
The keys of the `crons` definition are the names of the cron jobs.
The names must be unique.
If an application defines both a `web` instance and `worker` instances, cron jobs run only on the `web` instance.
See how to [get cron logs](/increase-observability/logs/access-logs.md#container-logs).
The following table shows the properties for each job:
| Name | Type | Required | Description |
|--------------------|----------------------------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `spec` | `string` | Yes | The [cron specification](https://en.wikipedia.org/wiki/Cron#Cron_expression). To prevent competition for resources that might hurt performance, use `H` in definitions to indicate an unspecified but invariant time. For example, instead of using `0 * * * *` to indicate the cron job runs at the start of every hour, you can use `H * * * *` to indicate it runs every hour, but not necessarily at the start. This prevents multiple cron jobs from trying to start at the same time. |
| `commands` | A [cron commands dictionary](#cron-commands) | Yes | A definition of what commands to run when starting and stopping the cron job. |
| `shutdown_timeout` | `integer` | No | When a cron is canceled, this represents the number of seconds after which a `SIGKILL` signal is sent to the process to force terminate it. The default is `10` seconds. |
| `timeout` | `integer` | No | The maximum amount of time a cron can run before it's terminated. Defaults to the maximum allowed value of `86400` seconds (24 hours). |
Note that you can [cancel pending or running crons](/environments/cancel-activity.md).
### Cron commands
| Name | Type | Required | Description |
|---------|----------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `start` | `string` | Yes | The command that's run. It's run in [Dash](https://en.wikipedia.org/wiki/Almquist_shell). |
| `stop` | `string` | No | The command that's issued to give the cron command a chance to shutdown gracefully, such as to finish an active item in a list of tasks. Issued when a cron task is interrupted by a user through the CLI or Console. If not specified, a `SIGTERM` signal is sent to the process. |
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'nodejs:22'
crons:
mycommand:
spec: 'H * * * *'
commands:
start: sleep 60 && echo sleep-60-finished && date
stop: killall sleep
shutdown_timeout: 18
```
In this example configuration, the [cron specification](#crons) uses the `H` syntax.
### Example cron jobs
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'php:8.4'crons:# Run Drupal's cron tasks every 19 minutes.drupal:spec:'*/19 * * * *'commands:start:'cd web ; drush core-cron'# But also run pending queue tasks every 7 minutes.# Use an odd number to avoid running at the same time as the `drupal` cron.drush-queue:spec:'*/7 * * * *'commands:start:'cd web ; drush queue-run aggregator_feeds'
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'ruby:3.3'crons:# Execute a rake script every 19 minutes.ruby:spec:'*/19 * * * *'commands:start:'bundle exec rake some:task'
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'php:8.4'crons:# Run Laravel's scheduler every 5 minutes.scheduler:spec:'*/5 * * * *'commands:start:'php artisan schedule:run'
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"type:'php:8.4'crons:# Take a backup of the environment every day at 5:00 AM.snapshot:spec:05***commands:start:| # Only run for the production environment, aka main branch
if [ "$PLATFORM_ENVIRONMENT_TYPE" = "production" ]; then
croncape symfony ...
fi
### Conditional crons
If you want to set up customized cron schedules depending on the environment type,
define conditional crons.
To do so, use a configuration similar to the following:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'php:8.4'
crons:
update:
spec: '0 0 * * *'
commands:
start: |
if [ "$PLATFORM_ENVIRONMENT_TYPE" = production ]; then
upsun backup:create --yes --no-wait
upsun source-operation:run update --no-wait --yes
fi
```
### Cron job timing
The minimum time between cron jobs being triggered is 5 minutes.
For each app container, only one cron job can run at a time.
If a new job is triggered while another is running, the new job is paused until the other completes.
To minimize conflicts, a random offset is applied to all triggers.
The offset is a random number of seconds up to 20 minutes or the cron frequency, whichever is smaller.
Crons are also paused while activities such as [backups](/environments/backup) are running.
The crons are queued to run after the other activity finishes.
To run cron jobs in a timezone other than UTC, set the [timezone property](#primary-application-properties).
### Paused crons
[Preview environments](/glossary.md#preview-environment) are often used for a limited time and then abandoned.
While it's useful for environments under active development to have scheduled tasks,
unused environments don't need to run cron jobs.
To minimize unnecessary resource use,
crons on environments with no deployments are paused.
This affects all preview environments, _and_ production environment that do not yet have a domain attached to them.
Such environments with deployments within 14 days have crons with the status `running`.
If there haven't been any deployments within 14 days, the status is `paused`.
You can see the status in the Console
or using the CLI by running `upsun environment:info` and looking under `deployment_state`.
#### Restarting paused crons
If the crons on your preview environment are paused but you're still using them,
you can push changes to the environment or redeploy it.
To restart crons without changing anything:
Open the environment where you’d like the crons to run.
Click Redeploy next to the cron status of Paused.
Run the following command:
upsun redeploy
## Runtime
The following table presents the various possible modifications to your PHP or Lisp runtime:
| Name | Type | Language | Description |
|-----------------------------|------------------------------------------------------------|----------|--------------------------------------------------------------------------------------------|
| `extensions` | List of `string`s OR [extensions definitions](#extensions) | PHP | [PHP extensions](/languages/php/extensions.md) to enable. |
| `disabled_extensions` | List of `string`s | PHP | [PHP extensions](/languages/php/extensions.md) to disable. |
| `request_terminate_timeout` | `integer` | PHP | The timeout for serving a single request after which the PHP-FPM worker process is killed. |
| `sizing_hints` | A [sizing hints definition](#sizing-hints) | PHP | The assumptions for setting the number of workers in your PHP-FPM runtime. |
| `xdebug` | An Xdebug definition | PHP | The setting to turn on [Xdebug](/languages/php/xdebug.md). |
| `quicklisp` | Distribution definitions | Lisp | [Distributions for QuickLisp](/languages/lisp.md#quicklisp-options) to use. |
You can also set your [app's runtime timezone](/create-apps/timezone.md).
### Extensions
Note
You can now use the Upsun composable image (BETA) to install runtimes and tools in your application container.
If you’ve reached this section from another page and are using the composable image, enabling/disabling extensions should be placed under the stack key instead of what is listed below.
See how to configure extensions with the composable image.
You can enable [PHP extensions](/languages/php/extensions.md) just with a list of extensions:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'php:8.4'
runtime:
extensions:
- geoip
- tidy
```
Alternatively, if you need to include configuration options, use a dictionary for that extension:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'php:8.4'
runtime:
extensions:
- geoip
- name: blackfire
configuration:
server_id: foo
server_token: bar
```
In this case, the `name` property is required.
### Sizing hints
The following table shows the properties that can be set in `sizing_hints`:
| Name | Type | Default | Minimum | Description |
|-------------------|-----------|---------|---------|------------------------------------------------|
| `request_memory` | `integer` | 45 | 10 | The average memory consumed per request in MB. |
| `reserved_memory` | `integer` | 70 | 70 | The amount of memory reserved in MB. |
See more about [PHP-FPM workers and sizing](/languages/php/fpm.md).
## Source
The following table shows the properties that can be set in `source`:
| Name | Type | Required | Description |
|--------------|--------------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------|
| `operations` | An operations dictionary | | Operations that can be applied to the source code. See [source operations](../source-operations.md) |
| `root` | `string` | | The path where the app code lives. Defaults to the root project directory. Useful for [multi-app setups](../multi-app/_index.md). |
## Container profile
By default, Upsun allocates a container profile to each app and service depending on the range of resources it’s
expected to need.
Each container profile gives you access to a specific list of CPU and RAM combinations.
Using the Upsun CLI or Console, you can then pick a CPU and RAM combination for each of your apps and services.
- [Container profile types and resources](/manage-resources/adjust-resources#advanced-container-profiles)
- [Default container profiles](/manage-resources/adjust-resources#default-container-profiles) for runtime and service
containers
- [Customize resources using the `container_profile` key](/manage-resources/adjust-resources#adjust-a-container-profile)
## Additional hosts
If you're using a private network with specific IP addresses you need to connect to,
you might want to map those addresses to hostnames to better remember and organize them.
In such cases, you can add a map of those IP addresses to whatever hostnames you like.
Then when your app tries to access the hostname, it's sent to the proper IP address.
So in the following example, if your app tries to access `api.example.com`, it's sent to `192.0.2.23`.
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: 'php:8.4'
additional_hosts:
api.example.com: "192.0.2.23"
web.example.com: "203.0.113.42"
```
This is equivalent to adding the mapping to the `/etc/hosts` file for the container.
# App reference [Composable image](https://docs.upsun.com/create-apps/app-reference/composable-image.html)
The Upsun composable image provides enhanced flexibility when defining your app.
It allows you to install several runtimes and tools in your application container,
in a **"one image to rule them all"** approach.
The composable image is built on [Nix](https://nix.dev), which offers the following benefits:
- You can add as many packages to your application container as you need,
choosing from over 80,000 packages from [the Nixpkgs collection](https://search.nixos.org/packages).
- The packages you add are built in total isolation, so you can install different versions of the same package.
- With [Nix](https://nix.dev/reference/glossary#term-Nix), there are no undeclared dependencies in your source code.
What works on your local machine is guaranteed to work on any other machine.
This page introduces all the settings available to configure your composable image from your `.upsun/config.yaml` file
(usually located at the root of your Git repository).
Note that multi-app projects can be [set in various ways](../multi-app/_index.md).
If you're pressed for time, jump to this comprehensive [configuration example](../_index.md#comprehensive-example).
## Primary application properties
All application configuration takes place in a `.upsun/config.yaml` file, with each application configured
under a unique key beneath the top-level `applications` key.
It is possible to use multiple runtimes in a single application container,
for instance PHP, NodeJS and Python, while remaining in control of their versions.
For example, the unified `.upsun/config.yaml` file may look like the following:
```yaml {configFile="app"}
applications:
frontend:
stack:
- "php@8.4":
extensions:
- apcu
- sodium
- xsl
- pdo_sqlite
- "nodejs@22"
- "python@3.12"
# Additional frontend configuration
```
The following table presents all properties available at the level just below the unique application name (`frontend`
above).
The column _Set in instance?_ defines whether the given property can be overridden within a `web` or `workers` instance.
To override any part of a property, you have to provide the entire property.
| Name | Type | Required | Set in instance? | Description |
|--------------------|-----------------------------------------------------|----------|------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `stack` | An array of [Nix packages](#stack) | Yes | No | A list of packages from the Upsun collection of [supported runtimes](#supported-nix-packages) and/or from [NixPkgs](https://search.nixos.org/packages). |
| `relationships` | A dictionary of [relationships](#relationships) | | Yes | Connections to other services and apps. |
| `mounts` | A dictionary of [mounts](#mounts) | | Yes | Directories that are writable even after the app is built. Allocated disk for mounts is defined with a separate resource configuration call using `upsun resources:set`. |
| `web` | A [web instance](#web) | | N/A | How the web application is served. |
| `workers` | A [worker instance](#workers) | | N/A | Alternate copies of the application to run as background processes. |
| `timezone` | `string` | | No | The timezone for crons to run. Format: a [TZ database name](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). Defaults to `UTC`, which is the timezone used for all logs no matter the value here. See also [app runtime timezones](../timezone.md) |
| `access` | An [access dictionary](#access) | | Yes | Access control for roles accessing app environments. |
| `variables` | A [variables dictionary](#variables) | | Yes | Variables to control the environment. |
| `firewall` | A [firewall dictionary](#firewall) | | Yes | Outbound firewall rules for the application. |
| `hooks` | A [hooks dictionary](#hooks) | | No | What commands run at different stages in the build and deploy process. |
| `crons` | A [cron dictionary](#crons) | | No | Scheduled tasks for the app. |
| `source` | A [source dictionary](#source) | | No | Information on the app's source code and operations that can be run on it. |
| `additional_hosts` | An [additional hosts dictionary](#additional-hosts) | | Yes | Maps of hostnames to IP addresses. |
Note
The type, build, dependencies, and runtime keys are only supported when using a single-runtime image.
They are not supported when using the composable image.
They are replaced by the stack key.
## Stack
Use the ``stack`` key to define which runtimes and binaries you want to install in your application container.
Define them as a YAML array as follows:
```yaml {configFile="app"}
applications:
myapp:
stack: [ "@" ]
# OR
stack:
- "@"
```
To add a language to your stack, use the `@` format.
To add a tool to your stack, use the `` format, as no version is needed.
Warning
While technically available during the build phase, nix commands aren’t supported at runtime as the image becomes read-only.
When using the Upsun composable image, you don’t need nix commands.
Everything you install using the stack key is readily available to you as the binaries are linked and included in $PATH.
#### Primary runtime
If you add multiple runtimes to your application container,
the first declared runtime becomes the primary runtime.
The primary runtime is the one that is automatically started.
To start other declared runtimes, you need to start them manually, using [web commands](#web-commands).
To find out which start command to use, go to the [Languages](/languages/_index.md) section,
and visit the documentation page dedicated to your runtime.
Note
If you use PHP, note that PHP-FPM is only started automatically if PHP is defined as the primary runtime.
### Supported Nix packages
Note
The Nix packages listed in the following table are officially supported by Upsun to provide optimal user experience.
However, you can add any other packages from the Nixpkgs collection to your stack.
This includes packages from the unstable channel,
like FrankenPHP.
While available for you to install, packages that aren’t listed in the following table are supported by Nix itself, not Upsun.
Depending on the Nix package, you can select only the major runtime version,
or the major and minor runtime versions as shown in the table.
Security and other patches are applied automatically.
| **Language** | **Nix package** | **Supported version(s)** |
|----------------------------------------------|---------------|----------------------------------------|
| [Clojure](https://clojure.org/) | `clojure` | 1 |
| [Common Lisp (SBCL)](/languages/lisp.html) | `sbcl` | 2 |
| [Elixir](/languages/elixir.html) | `elixir` | 1.15 1.14 |
| [Go](/languages/go.html) | `golang` | 1.22 1.21 |
| [Java](/languages/java.html) | `java` | 21 |
| [Javascript/Bun](https://bun.sh/) | `bun` | 1 |
| [JavaScript/Node.js](/languages/nodejs.html) | `nodejs` | 22 20 18 |
| [Perl](https://www.perl.org/) | `perl` | 5 |
| [PHP](/languages/php.html) | `php` | 8.3 8.2 8.1 |
| [Python](/languages/python.html) | `python` | 3.12 3.11 3.10 3.9 2.7 |
| [Ruby](/languages/ruby.html) | `ruby` | 3.3 3.2 3.1 |
**Example:**
You want to add PHP version 8.4 and ``facedetect`` to your application container.
To do so, use the following configuration:
```yaml {configFile="app"}
applications:
myapp:
stack: [ "php@8.4", "facedetect" ]
# OR
stack:
- "php@8.4"
- "facedetect"
```
### PHP extensions and Python packages
When you add PHP or Python to your application container,
you can define which extensions (for PHP) or packages (for Python) you also want to add to your stack.
To find out which extensions you can install with your runtime,
follow these steps:
1. Go to the [NixOS search](https://search.nixos.org/).
2. Enter a runtime and click **Search**.
3. In the **Package sets** side bar, select the right set of extensions/packages for your runtime version.
You can choose the desired extensions/packages from the filtered results.

#### Install PHP extensions
To enable [PHP extensions](/languages/php/extensions.md),
specify a list of `extensions` below the language definition.
To disable [PHP extensions](/languages/php/extensions.md),
specify a list of `disabled_extensions` below the language definition.
For instance:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
stack:
- "php@8.4":
extensions:
- apcu
- sodium
- xsl
- pdo_sqlite
disabled_extensions:
- gd
```
Note
To help you find out the name of the PHP package you want to use,
some maintainers provide a PHP upstream extension value in the NixOS search engine.
If this information is not provided, note that PHP package names on NixOS always respect the <PHP><VERSION>Extensions.<EXTENSION-NAME> format.
Therefore, you can copy the <EXTENSION-NAME> as shown in the NixOS search results, and use it in your configuration.
#### Install Python packages
To install Python packages, add them to your stack as new packages.
To do so, use the full name of the package.
For instance, to install [``python312Packages.yq``](https://search.nixos.org/packages?channel=unstable&show=python312Packages.yq),
use the following configuration:
```yaml {configFile="app"}
applications:
myapp:
stack:
- "python@3.12"
- "python312Packages.yq" # python package specific
```
Alternatively, if you need to include configuration options for your extensions, use either your ``php.ini`` file or [environment variables](/development/variables/set-variables.md).
### Example configuration
Here is a full composable image configuration example. Note the use of the `@` format.
```yaml {configFile="app"}
applications:
myapp:
stack:
- "php@8.4":
extensions:
- apcu
- sodium
- xsl
- pdo_sqlite
- "python@3.12"
- "python312Packages.yq" # python package specific
- "yq" # tool
```
### Combine single-runtime and composable images
In a [multiple application context](/create-apps/multi-app/_index.md),
you can use a mix of [single-runtime images](/create-apps/app-reference/single-runtime-image.md)
and [composable images](/create-apps/app-reference/composable-image.md).
Here is an example configuration including a ``frontend`` app and a ``backend`` app:
```yaml {configFile="app"}
applications:
frontend:
stack:
- "php@8.4":
extensions:
- apcu
- sodium
- xsl
- pdo_sqlite
- "python@3.12"
- "python312Packages.yq" # python package specific
backend:
type: 'nodejs:22
```
Note
If you add multiple runtimes to your application container,
the first declared runtime becomes the primary runtime.
The primary runtime is the one that is automatically started.
To start other declared runtimes, you need to start them manually, using web commands.
To find out which start command to use, go to the Languages section,
and visit the documentation page dedicated to your language.
If you use PHP, note that PHP-FPM is only started automatically if PHP is defined as the primary runtime.
## Resources
Resources for application containers are not committed to YAML files, but instead managed over the API using either the
Console or the `upsun resources:set` command.
For more information, see how to [manage resources](/manage-resources.md).
Note
Composable image container profile defaults to HIGH_CPU.
If multiple runtimes are added to your stack,
you would need to change
the default container_profile or change default CPU and RAM ratio on first deployment using the following
commands:
upsun push --resources-init=manual
## Relationships
To allow containers in your project to communicate with one another,
you need to define relationships between them.
You can define a relationship between an app and a service, or [between two apps](/create-apps/multi-app/relationships.md).
The quickest way to define a relationship between your app and a service
is to use the service's default endpoint.
However, some services allow you to define multiple databases, cores, and/or permissions.
In these cases, you can't rely on default endpoints.
Instead, you can explicitly define multiple endpoints when setting up your relationships.
Note
App containers don’t have a default endpoint like services.
To connect your app to another app in your project,
you need to explicitly define the http endpoint as the endpoint to connect both apps.
For more information, see how to define relationships between your apps.
Availability
New syntax (default and explicit endpoints) described below is supported by most, but not all, image types
(Relationship 'SERVICE_NAME' of application 'myapp' ... targets a service without a valid default endpoint configuration.).
This syntax is currently being rolled out for all images.
If you encounter this error, use the “legacy” Upsun configuration noted at the bottom of this section.
To define a relationship between your app and a service:
The SERVICE_NAME is the name of the service as defined in its configuration.
It is used as the relationship name, and associated with a null value.
This instructs Upsun to use the service’s default endpoint to connect your app to the service.
For example, if you define the following configuration:
.upsun/config.yaml
applications:APP_NAME:# ...relationships:mariadb:
Upsun looks for a service named mariadb in your .upsun/config.yaml file,
and connects your app to it through the service’s default endpoint.
For reference, the equivalent configuration using explicit endpoints would be the following:
RELATIONSHIP_NAME is the name you want to give to the relationship.
SERVICE_NAME is the name of the service as defined in its configuration.
ENDPOINT_NAME is the endpoint your app will use to connect to the service (refer to the service reference to know which value to use).
For example, to define a relationship named database that connects your app to a service called mariadb through the db1 endpoint,
use the following configuration:
.upsun/config.yaml
applications:APP_NAME:# ...relationships:database:# The name of the relationship.service:mariadbendpoint:db1
For more information on how to handle multiple databases, multiple cores,
and/or different permissions with services that support such features,
see each service’s dedicated page:
Feel free to use this until the default and explicit endpoint syntax is supported on all images.
## Available disk space
Disk for application containers are not committed to YAML files, but instead managed over the API using either the
Console or the `upsun resources:set` command.
For more information, see how to [manage resources](/manage-resources.md).
### Downsize a disk
You can decrease the size of an existing disk for an app. If you do so, be aware that:
- Backups from before the downsize are incompatible and can no longer be used. You need to [create new backups](/environments/backup).
- The downsize fails if there’s more data on the disk than the desired size.
## Mounts
After your app is built, its file system is read-only.
To make changes to your app's code, you need to use Git.
For enhanced flexibility, Upsun allows you to define and use writable directories called "mounts".
Mounts give you write access to files generated by your app (such as cache and log files)
and uploaded files without going through Git.
When you define a mount, you are mounting an external directory to your app container,
much like you would plug a hard drive into your computer to transfer data.
### Define a mount
To define a mount, use the following configuration:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
stack: [ "nodejs@22" ]
mounts:
'MOUNT_PATH':
source: MOUNT_TYPE
source_path: SOURCE_PATH_LOCATION
```
MOUNT_PATH is the path to your mount **within the app container** (relative to the app's root).
If you already have a directory with that name, you get a warning that it isn't accessible after the build.
See how to [troubleshoot the warning](../troubleshoot-mounts.md#overlapping-folders).
| Name | Type | Required | Description |
|---------------|--------------------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `source` | `storage`, `tmp`, or `service` | Yes | Specifies the type of the mount:
- By design, `storage` mounts can be shared between instances of the same app. You can also configure them so they are [shared between different apps](#share-a-mount-between-several-apps).
-`instance` mounts are local mounts. Unique to your app, they are useful to store files that remain local to the app instance, such as application logs.
- `tmp` mounts are local ephemeral mounts, where an external directory is mounted to the `/tmp` directory of your app. The content of a `tmp` mount **may be removed during infrastructure maintenance operations**. Therefore, `tmp` mounts allow you to **store files that you’re not afraid to lose**, such as your application cache that can be seamlessly rebuilt. Note that the `/tmp` directory has **a maximum allocation of 8 GB**.
- `service` mounts can be useful if you want to explicitly define and use a [Network Storage](/add-services/network-storage.md) service to share data between different apps (instead of using a `storage` mount). |
| `source_path` | `string` | No | Specifies where the mount points **inside the [external directory](#mounts)**.
- If you explicitly set a `source_path`, your mount points to a specific subdirectory in the external directory.
- If the `source_path` is an empty string (`""`), your mount points to the entire external directory.
- If you don't define a `source_path`, Upsun uses the MOUNT_PATH as default value, without leading or trailing slashes.For example, if your mount lives in the `/web/uploads/` directory in your app container, it will point to a directory named `web/uploads` in the external directory. **WARNING:** Changing the name of your mount affects the `source_path` when it's undefined. See [how to ensure continuity](#ensure-continuity-when-changing-the-name-of-your-mount) and maintain access to your files. |
| `service` | `string` | | The purpose of the `service` key depends on your use case. In a multi-app context where a `storage` mount is shared between apps, `service` is required. Its value is the name of the app whose mount you want to share. See how to [share a mount between several apps](#share-a-mount-between-several-apps). In a multi-app context where a [Network Storage service](/add-services/network-storage.md) (`service` mount) is shared between apps, `service` is required and specifies the name of that Network Storage. |
The accessibility to the web of a mounted directory depends on the [`web.locations` configuration](#web).
Files can be all public, all private, or with different rules for different paths and file types.
Note that when you remove a `tmp` mount from your `.upsun/config.yaml` file,
the mounted directory isn't deleted.
The files still exist on disk until manually removed,
or until the app container is moved to another host during a maintenance operation.
### Example configuration
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
stack: [ "nodejs@22" ]
mounts:
'web/uploads':
source: storage
source_path: uploads
'/.tmp_platformsh':
source: tmp
source_path: files/.tmp_platformsh
'/build':
source: storage
source_path: files/build
'/.cache':
source: tmp
source_path: files/.cache
'/node_modules/.cache':
source: tmp
source_path: files/node_modules/.cache
```
### Ensure continuity when changing the name of your mount
Changing the name of your mount affects the default `source_path`.
Say you have a `/my/cache/` mount with an undefined `source_path`:
```yaml {configFile="app"}
mounts:
'/my/cache/':
source: tmp
```
If you rename the mount to `/cache/files/`, it will point to a new, empty `/cache/files/` directory.
To ensure continuity, you need to explicitly define the `source_path` as the previous name of the mount, without leading
or trailing slashes:
```yaml {configFile="app"}
mounts:
'/cache/files/':
source: tmp
source_path: my/cache
```
The `/cache/files/` mount will point to the original `/my/cache/` directory, maintaining access to all your existing
files in that directory.
### Share a mount between several apps
By design, [`storage` mounts](#mounts) are shared **between different instances of the same app**,
which enables [horizontal scaling](/manage-resources/_index.md).
In a [multi-application context](/create-apps/multi-app/_index.md),
you can even share a `storage` mount **between different applications** in the same project.
To do so, you need to define a `storage` mount in each of your app containers,
and point each of those mounts to the same shared external network directory.
Use the following configuration:
```yaml {configFile="app"}
applications:
app1:
mounts:
'MOUNT_PATH_1':
source: storage
source_path: SOURCE_PATH_LOCATION
app2:
mounts:
'MOUNT_PATH_2':
source: storage
service: app1
source_path: SOURCE_PATH_LOCATION
```
- MOUNT_PATH_1 and MOUNT_PATH_2 are the paths to each mount **within their
respective app container** (relative to the app's root).
- When configuring the first `storage` mount, you don't need to include the `service` key.
The first mount implicitly points to an external network directory.
The `service` key is required for subsequent mounts, to ensure they use the same external network directory as the
first mount.
- The `source_path` allows you to point each mount to the same subdirectory **within the shared external network
directory**.
Example
You have a backend app and a frontend app.
You want both apps to share data from the same mount.
Follow these steps:
In your backend app configuration, define a storage mount:
.upsun/config.yaml
applications:backend:mounts:var/uploads:#The path to your mount within the backend app container.source:storagesource_path:backend/uploads#The path to the source of the mount within the external network directory.
This creates a storage mount named var/uploads in the backend app container.
The mount points to the backend/uploads directory within an external network directory.
In your frontend app configuration, define another storage mount:
.upsun/config.yaml
applications:backend:mounts:var/uploads:source:storagesource_path:backend/uploadsfrontend:mounts:web/uploads:#The path to your mount within the frontend app container.source:storageservice:backend#The name of the other app, so the mount can point to the same external network directory as that other app's mount.source_path:backend/uploads#The path to the source of the mount within the shared external network directory.
This creates another storage mount named web/uploads in the frontend app container.
The service key allows you to specify that the web/uploads mount should use the same external network directory
as the mount previously defined in the backend app container.
The source_path key specifies which subdirectory within the external network directory both mounts should share (
here, the backend/uploads directory).
Note that another way to share data between apps through a mount is by
explicitly [defining a Network Storage service](/add-services/network-storage.md).
### Local mounts
If you need a local mount (i.e. unique per container),
Upsun allows you to mount a directory within the `/tmp` directory of your app.
However, the following limitations apply:
- Content from `tmp` mounts is removed when your app container is moved to another host during an infrastructure
maintenance operation
- The `/tmp` directory has a [maximum allocation of 8 GB](/create-apps/troubleshoot-disks.md#no-space-left-on-device)
Therefore, `tmp` mounts are ideal to store non-critical data, such as your application cache which can be seamlessly
rebuilt,
but aren't suitable for storing files that are necessary for your app to run smoothly.
Note that Upsun will provide new local mounts in the near future.
### Overlapping mounts
The locations of mounts as they are visible to application containers can overlap somewhat.
For example:
```yaml {configFile="app"}
applications:
myapp:
# ...
mounts:
'var/cache_a':
source: storage
source_path: cacheA
'var/cache_b':
source: tmp
source_path: cacheB
'var/cache_c':
source: instance
source_path: cacheC
```
In this case, it does not matter that each mount is of a different `source` type.
Each mount is restricted to a subfolder within `var`, and all is well.
The following, however, is not allowed and will result in a failure:
```yaml {configFile="app"}
applications:
myapp:
# ...
mounts:
'var/':
source: storage
source_path: cacheA
'var/cache_b':
source: tmp
source_path: cacheB
'var/cache_c':
source: instance
source_path: cacheC
```
The `storage` mount type specifically exists to share data between instances of the same application, whereas `tmp` and `instance` are meant to restrict data to build time and runtime of a single application instance, respectively.
These allowances are not compatible, and will result in an error if pushed.
## Web
Use the `web` key to configure the web server running in front of your app.
| Name | Type | Required | Description |
|-------------|--------------------------------------------|-------------------------------|------------------------------------------------------|
| `commands` | A [web commands dictionary](#web-commands) | See [note](#required-command) | The command to launch your app. |
| `upstream` | An [upstream dictionary](#upstream) | | How the front server connects to your app. |
| `locations` | A [locations dictionary](#locations) | | How the app container responds to incoming requests. |
See some [examples of how to configure what's served](../web/_index.md).
### Web commands
| Name | Type | Required | Description |
|-------------|----------|-------------------------------|-----------------------------------------------------------------------------------------------------|
| `pre_start` | `string` | | Command run just prior to `start`, which can be useful when you need to run _per-instance_ actions. |
| `start` | `string` | See [note](#required-command) | The command to launch your app. If it terminates, it's restarted immediately. |
Example:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
stack: [ "python@3.9" ]
web:
commands:
start: 'uwsgi --ini conf/server.ini'
```
This command runs every time your app is restarted, regardless of whether or not new code is deployed.
Note
Never “background” a start process using &.
That’s interpreted as the command terminating and the supervisor process starts a second copy,
creating an infinite loop until the container crashes.
Just run it as normal and allow the Upsun supervisor to manage it.
#### Required command
On all containers other than PHP, the value for `start` should be treated as required.
On PHP containers, it's optional and defaults to starting PHP-FPM (`/usr/bin/start-php-app`).
It can also be set explicitly on a PHP container to run a dedicated process,
such as [React PHP](https://github.com/platformsh-examples/platformsh-example-reactphp)
or [Amp](https://github.com/platformsh-examples/platformsh-example-amphp).
See how to set up [alternate start commands on PHP](/languages/php/_index.md#alternate-start-commands).
### Upstream
| Name | Type | Required | Description | Default |
|-----------------|---------------------|----------|-------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------|
| `socket_family` | `tcp` or `unix` | | Whether your app listens on a Unix or TCP socket. | Defaults to `tcp` for all [primary runtimes](#primary-runtime) except PHP; for PHP the default is `unix`. |
| `protocol` | `http` or `fastcgi` | | Whether your app receives incoming requests over HTTP or FastCGI. | Default varies based on the [primary runtimes](#primary-runtime). |
For PHP, the defaults are configured for PHP-FPM and shouldn't need adjustment.
For all other containers, the default for `protocol` is `http`.
The following example is the default on non-PHP containers:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
stack: [ "python@3.9" ]
web:
upstream:
socket_family: tcp
protocol: http
```
#### Where to listen
Where to listen depends on your setting for `web.upstream.socket_family` (defaults to `tcp`).
| `socket_family` | Where to listen |
|-----------------|---------------------------------------------------------------------------------------------------------------------------------------|
| `tcp` | The port specified by the [`PORT` environment variable](/development/variables/use-variables.md#use-provided-variables) |
| `unix` | The Unix socket file specified by the [`SOCKET` environment variable](/development/variables/use-variables.md#use-provided-variables) |
If your application isn't listening at the same place that the runtime is sending requests,
you see `502 Bad Gateway` errors when you try to connect to your website.
### Locations
Each key in the `locations` dictionary is a path on your site with a leading `/`.
For `example.com`, a `/` matches `example.com/` and `/admin` matches `example.com/admin`.
When multiple keys match an incoming request, the most-specific applies.
The following table presents possible properties for each location:
| Name | Type | Default | Description |
|---------------------|------------------------------------------------------|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `root` | `string` | | The directory to serve static assets for this location relative to the app's root directory ([see `source.root`](#source)). Must be an actual directory inside the root directory. |
| `passthru` | `boolean` or `string` | `false` | Whether to forward disallowed and missing resources from this location to the app. A string is a path with a leading `/` to the controller, such as `/index.php`.
If your app is in PHP, when setting `passthru` to `true`, you might want to set `scripts` to `false` for enhanced security. This prevents PHP scripts from being executed from the specified location. You might also want to set `allow` to `false` so that not only PHP scripts can't be executed, but their source code also can't be delivered. |
| `index` | Array of `string`s or `null` | | Files to consider when serving a request for a directory. When set, requires access to the files through the `allow` or `rules` keys. |
| `expires` | `string` | `-1` | How long static assets are cached. The default means no caching. Setting it to a value enables the `Cache-Control` and `Expires` headers. Times can be suffixed with `ms` = milliseconds, `s` = seconds, `m` = minutes, `h` = hours, `d` = days, `w` = weeks, `M` = months/30d, or `y` = years/365d. |
| `allow` | `boolean` | `true` | Whether to allow serving files which don't match a rule. |
| `scripts` | `boolean` | | Whether to allow scripts to run. Doesn't apply to paths specified in `passthru`. Meaningful only on PHP containers. |
| `headers` | A headers dictionary | | Any additional headers to apply to static assets, mapping header names to values. Responses from the app aren't affected. |
| `request_buffering` | A [request buffering dictionary](#request-buffering) | See below | Handling for chunked requests. |
| `rules` | A [rules dictionary](#rules) | | Specific overrides for specific locations. |
#### Rules
The rules dictionary can override most other keys according to a regular expression.
The key of each item is a regular expression to match paths exactly.
If an incoming request matches the rule, it's handled by the properties under the rule,
overriding any conflicting rules from the rest of the `locations` dictionary.
Under `rules`, you can set all of the other possible [`locations` properties](#locations)
except `root`, `index` and `request_buffering`.
In the following example, the `allow` key disallows requests for static files anywhere in the site.
This is overridden by a rule that explicitly allows common image file formats.
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
stack: [ "python@3.9" ]
web:
locations:
'/':
# Handle dynamic requests
root: 'public'
passthru: '/index.php'
# Disallow static files
allow: false
rules:
# Allow common image files only.
'\.(jpe?g|png|gif|svgz?|css|js|map|ico|bmp|eot|woff2?|otf|ttf)$':
allow: true
```
#### Request buffering
Request buffering is enabled by default to handle chunked requests as most app servers don't support them.
The following table shows the keys in the `request_buffering` dictionary:
| Name | Type | Required | Default | Description |
|--------------------|-----------|----------|---------|-------------------------------------------|
| `enabled` | `boolean` | Yes | `true` | Whether request buffering is enabled. |
| `max_request_size` | `string` | | `250m` | The maximum size to allow in one request. |
The default configuration would look like this:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
stack: [ "python@3.9" ]
web:
locations:
'/':
passthru: true
request_buffering:
enabled: true
max_request_size: 250m
```
## Workers
Workers are exact copies of the code and compilation output as a `web` instance after a [`build` hook](#hooks).
They use the same container image.
Workers can't accept public requests and so are suitable only for background tasks.
If they exit, they're automatically restarted.
The keys of the `workers` definition are the names of the workers.
You can then define how each worker differs from the `web` instance using
the [top-level properties](#primary-application-properties).
Each worker can differ from the `web` instance in all properties _except_ for:
- `crons` as cron jobs don't run on workers
- `hooks` as the `build` hook must be the same
and the `deploy` and `post_deploy` hooks don't run on workers.
A worker named `queue` that was small and had a different start command could look like this:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
stack: [ "python@3.9" ]
workers:
queue:
commands:
start: |
./worker.sh
```
Workers require resource definition using `upsun resources:set`, same as application containers.
For more information, see how to [manage resources](/manage-resources.md).
## Access
The `access` dictionary has one allowed key:
| Name | Allowed values | Default | Description |
|-------|-------------------------------------|---------------|-----------------------------------------------------------------------|
| `ssh` | `admin`, `contributor`, or `viewer` | `contributor` | Defines the minimum role required to access app environments via SSH. |
In the following example, only users with `admin` permissions for the
given [environment type](/administration/users.md#environment-type-roles)
can access the deployed environment via SSH:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
stack: [ "python@3.9" ]
access:
ssh: admin
```
## Variables
Upsun provides a number of ways to set [variables](/development/variables/_index.md).
Variables set in your app configuration have the lowest precedence,
meaning they're overridden by any conflicting values provided elsewhere.
All variables set in your app configuration must have a prefix.
Some [prefixes have specific meanings](/development/variables/_index.md#variable-prefixes).
Variables with the prefix `env` are available as a separate environment variable.
All other variables are available in
the [`PLATFORM_VARIABLES` environment variable](/development/variables/use-variables.md#use-provided-variables).
The following example sets two variables:
- A variable named `env:AUTHOR` with the value `Juan` that's available in the environment as `AUTHOR`
- A variable named `d8config:system.site:name` with the value `My site rocks`
that's available in the `PLATFORM_VARIABLES` environment variable
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
stack: [ "python@3.9" ]
variables:
env:
AUTHOR: 'Juan'
d8config:
"system.site:name": 'My site rocks'
```
You can also define and access more [complex values](/development/variables/use-variables.md#access-complex-values).
## Firewall
Set limits in outbound traffic from your app with no impact on inbound requests.
The `outbound` key is required and contains one or more rules.
The rules define what traffic is allowed; anything unspecified is blocked.
Each rule has the following properties where at least one is required and `ips` and `domains` can't be specified
together:
| Name | Type | Default | Description |
|-----------|---------------------|-----------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `ips` | Array of `string`s | `["0.0.0.0/0"]` | IP addresses in [CIDR notation](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing). See a [CIDR format converter](https://www.ipaddressguide.com/cidr). |
| `domains` | Array of `string`s | | [Fully qualified domain names](https://en.wikipedia.org/wiki/Fully_qualified_domain_name) to specify specific destinations by hostname. |
| `ports` | Array of `integer`s | | Ports from 1 to 65535 that are allowed. If any ports are specified, all unspecified ports are blocked. If no ports are specified, all ports are allowed. Port `25`, the SMTP port for sending email, is always blocked. |
The default settings would look like this:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
stack: [ "python@3.9" ]
firewall:
outbound:
- ips: [ "0.0.0.0/0" ]
```
### Support for rules
Where outbound rules for firewalls are supported in all environments.
### Multiple rules
Multiple firewall rules can be specified.
In such cases, a given outbound request is allowed if it matches _any_ of the defined rules.
So in the following example requests to any IP on port 80 are allowed
and requests to 1.2.3.4 on either port 80 or 443 are allowed:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
stack: [ "python@3.9" ]
firewall:
outbound:
- ips: [ "1.2.3.4/32" ]
ports: [ 443 ]
- ports: [ 80 ]
```
### Outbound traffic to CDNs
Be aware that many services are behind a content delivery network (CDN).
For most CDNs, routing is done via domain name, not IP address,
so thousands of domain names may share the same public IP addresses at the CDN.
If you allow the IP address of a CDN, you are usually allowing many or all of the other customers hosted behind that
CDN.
### Outbound traffic by domain
You can filter outbound traffic by domain.
Using domains in your rules rather than IP addresses is generally more specific and secure.
For example, if you use an IP address for a service with a CDN,
you have to allow the IP address for the CDN.
This means that you allow potentially hundreds or thousands of other servers also using the CDN.
An example rule filtering by domain:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
stack: [ "python@3.9" ]
firewall:
outbound:
- protocol: tcp
domains: [ "api.stripe.com", "api.twilio.com" ]
ports: [ 80, 443 ]
- protocol: tcp
ips: [ "1.2.3.4/29","2.3.4.5" ]
ports: [ 22 ]
```
#### Determine which domains to allow
To determine which domains to include in your filtering rules,
find the domains your site has requested the DNS to resolve.
Run the following command to parse your server’s `dns.log` file
and display all Fully Qualified Domain Names that have been requested:
```bash
awk '/query\[[^P]\]/ { print $6 | "sort -u" }' /var/log/dns.log
```
The output includes all DNS requests that were made, including those blocked by your filtering rules.
It doesn't include any requests made using an IP address.
Example output:
```bash
facebook.com
fastly.com
upsun.com
www.google.com
www.upsun.com
```
## Hooks
There are three different hooks that run as part of the process of building and deploying your app.
These are places where you can run custom scripts.
They are: the `build` hook, the `deploy` hook, and the `post_deploy` hook.
Only the `build` hook is run for [worker instances](#workers), while [web instances](#web) run all three.
The process is ordered as:
1. Variables accessible at build time become available.
1. The `build` hook is run.
1. The file system is changed to read only (except for any [mounts](#mounts)).
1. The app container starts. Variables accessible at runtime and services become available.
1. The `deploy` hook is run.
1. The app container begins accepting requests.
1. The `post_deploy` hook is run.
Note that if an environment changes by no code changes, only the last step is run.
If you want the entire process to run, see how
to [manually trigger builds](/development/troubleshoot.md#manually-trigger-builds).
### Writable directories during build
During the `build` hook, there are three writeable directories:
- `PLATFORM_APP_DIR`:
Where your code is checked out and the working directory when the `build` hook starts.
Becomes the app that gets deployed.
- `PLATFORM_CACHE_DIR`:
Persists between builds, but isn't deployed.
Shared by all builds on all branches.
- `/tmp`:
Isn't deployed and is wiped between each build.
Note that `PLATFORM_CACHE_DIR` is mapped to `/tmp`
and together they offer about 8GB of free space.
### Hook failure
Each hook is executed as a single script, so they're considered to have failed only if the final command in them fails.
To cause them to fail on the first failed command, add `set -e` to the beginning of the hook.
If a `build` hook fails for any reason, the build is aborted and the deploy doesn't happen.
Note that this only works for `build` hooks --
if other hooks fail, the app is still deployed.
#### Automated testing
It’s preferable that you set up and run automated tests in a dedicated CI/CD tool.
Relying on Upsun hooks for such tasks can prove difficult.
During the `build` hook, you can halt the deployment on a test failure but the following limitations apply:
- Access to services such as databases, Redis, Vault KMS, and even writable mounts is disabled.
So any testing that relies on it is sure to fail.
- If you haven’t made changes to your app, an existing build image is reused and the build hook isn’t run.
- Test results are written into your app container, so they might get exposed to a third party.
During the `deploy` hook, you can access services but **you can’t halt the deployment based on a test failure**.
Note that there are other downsides:
- Your app container is read-only during the deploy hook,
so if your tests need to write reports and other information, you need to create a file mount for them.
- Your app can only be deployed once the deploy hook has been completed.
Therefore, running automated testing via the deploy hook generates slower deployments.
- Your environment isn’t available externally during the deploy hook.
Unit and integration testing might work without the environment being available,
but you can’t typically perform end-to-end testing until after the environment is up and available.
## Crons
The keys of the `crons` definition are the names of the cron jobs.
The names must be unique.
If an application defines both a `web` instance and `worker` instances, cron jobs run only on the `web` instance.
See how to [get cron logs](/increase-observability/logs/access-logs.md#container-logs).
The following table shows the properties for each job:
| Name | Type | Required | Description |
|--------------------|----------------------------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `spec` | `string` | Yes | The [cron specification](https://en.wikipedia.org/wiki/Cron#Cron_expression). To prevent competition for resources that might hurt performance, use `H` in definitions to indicate an unspecified but invariant time. For example, instead of using `0 * * * *` to indicate the cron job runs at the start of every hour, you can use `H * * * *` to indicate it runs every hour, but not necessarily at the start. This prevents multiple cron jobs from trying to start at the same time. |
| `commands` | A [cron commands dictionary](#cron-commands) | Yes | A definition of what commands to run when starting and stopping the cron job. |
| `shutdown_timeout` | `integer` | No | When a cron is canceled, this represents the number of seconds after which a `SIGKILL` signal is sent to the process to force terminate it. The default is `10` seconds. |
| `timeout` | `integer` | No | The maximum amount of time a cron can run before it's terminated. Defaults to the maximum allowed value of `86400` seconds (24 hours). |
Note that you can [cancel pending or running crons](/environments/cancel-activity.md).
### Cron commands
| Name | Type | Required | Description |
|---------|----------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `start` | `string` | Yes | The command that's run. It's run in [Dash](https://en.wikipedia.org/wiki/Almquist_shell). |
| `stop` | `string` | No | The command that's issued to give the cron command a chance to shutdown gracefully, such as to finish an active item in a list of tasks. Issued when a cron task is interrupted by a user through the CLI or Console. If not specified, a `SIGTERM` signal is sent to the process. |
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
stack: [ "nodejs@22" ]
crons:
mycommand:
spec: 'H * * * *'
commands:
start: sleep 60 && echo sleep-60-finished && date
stop: killall sleep
shutdown_timeout: 18
```
In this example configuration, the [cron specification](#crons) uses the `H` syntax.
### Example cron jobs
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"stack:["php@8.4"]crons:# Run Drupal's cron tasks every 19 minutes.drupal:spec:'*/19 * * * *'commands:start:'cd web ; drush core-cron'# But also run pending queue tasks every 7 minutes.# Use an odd number to avoid running at the same time as the `drupal` cron.drush-queue:spec:'*/7 * * * *'commands:start:'cd web ; drush queue-run aggregator_feeds'
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"stack:["ruby@3.3"]crons:# Execute a rake script every 19 minutes.ruby:spec:'*/19 * * * *'commands:start:'bundle exec rake some:task'
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"stack:["php@8.4"]crons:# Run Laravel's scheduler every 5 minutes.scheduler:spec:'*/5 * * * *'commands:start:'php artisan schedule:run'
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"/"stack:["php@8.4"]crons:# Take a backup of the environment every day at 5:00 AM.snapshot:spec:05***commands:start:| # Only run for the production environment, aka main branch
if [ "$PLATFORM_ENVIRONMENT_TYPE" = "production" ]; then
croncape symfony ...
fi
### Conditional crons
If you want to set up customized cron schedules depending on the environment type,
define conditional crons.
To do so, use a configuration similar to the following:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
stack: [ "php@8.4" ]
crons:
update:
spec: '0 0 * * *'
commands:
start: |
if [ "$PLATFORM_ENVIRONMENT_TYPE" = production ]; then
upsun backup:create --yes --no-wait
upsun source-operation:run update --no-wait --yes
fi
```
### Cron job timing
The minimum time between cron jobs being triggered is 5 minutes.
For each app container, only one cron job can run at a time.
If a new job is triggered while another is running, the new job is paused until the other completes.
To minimize conflicts, a random offset is applied to all triggers.
The offset is a random number of seconds up to 20 minutes or the cron frequency, whichever is smaller.
Crons are also paused while activities such as [backups](/environments/backup) are running.
The crons are queued to run after the other activity finishes.
To run cron jobs in a timezone other than UTC, set the [timezone property](#primary-application-properties).
### Paused crons
[Preview environments](/glossary.md#preview-environment) are often used for a limited time and then abandoned.
While it's useful for environments under active development to have scheduled tasks,
unused environments don't need to run cron jobs.
To minimize unnecessary resource use,
crons on environments with no deployments are paused.
This affects all preview environments, _and_ production environment that do not yet have a domain attached to them.
Such environments with deployments within 14 days have crons with the status `running`.
If there haven't been any deployments within 14 days, the status is `paused`.
You can see the status in the Console
or using the CLI by running `upsun environment:info` and looking under `deployment_state`.
#### Restarting paused crons
If the crons on your preview environment are paused but you're still using them,
you can push changes to the environment or redeploy it.
To restart crons without changing anything:
Open the environment where you’d like the crons to run.
Click Redeploy next to the cron status of Paused.
Run the following command:
upsun redeploy
### Sizing hints
The following table shows the properties that can be set in `sizing_hints`:
| Name | Type | Default | Minimum | Description |
|-------------------|-----------|---------|---------|------------------------------------------------|
| `request_memory` | `integer` | 45 | 10 | The average memory consumed per request in MB. |
| `reserved_memory` | `integer` | 70 | 70 | The amount of memory reserved in MB. |
See more about [PHP-FPM workers and sizing](/languages/php/fpm.md).
## Source
The following table shows the properties that can be set in `source`:
| Name | Type | Required | Description |
|--------------|--------------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------|
| `operations` | An operations dictionary | | Operations that can be applied to the source code. See [source operations](../source-operations.md) |
| `root` | `string` | | The path where the app code lives. Defaults to the root project directory. Useful for [multi-app setups](../multi-app/_index.md). |
## Container profile
By default, Upsun allocates a container profile to each app and service depending on the range of resources it’s
expected to need.
Each container profile gives you access to a specific list of CPU and RAM combinations.
Using the Upsun CLI or Console, you can then pick a CPU and RAM combination for each of your apps and services.
- [Container profile types and resources](/manage-resources/adjust-resources#advanced-container-profiles)
- [Default container profiles](/manage-resources/adjust-resources#default-container-profiles) for runtime and service
containers
- [Customize resources using the `container_profile` key](/manage-resources/adjust-resources#adjust-a-container-profile)
## Additional hosts
If you're using a private network with specific IP addresses you need to connect to,
you might want to map those addresses to hostnames to better remember and organize them.
In such cases, you can add a map of those IP addresses to whatever hostnames you like.
Then when your app tries to access the hostname, it's sent to the proper IP address.
So in the following example, if your app tries to access `api.example.com`, it's sent to `192.0.2.23`.
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
stack: [ "php@8.4" ]
additional_hosts:
api.example.com: "192.0.2.23"
web.example.com: "203.0.113.42"
```
This is equivalent to adding the mapping to the `/etc/hosts` file for the container.
# PHP [PHP-FPM sizing](https://docs.upsun.com/languages/php/fpm.html)
Note
You can now use composable image (BETA) to install runtimes and tools in your application container. To find out more, see the dedicated documentation page.
PHP-FPM helps improve your app's performance
by maintaining pools of workers that can process PHP requests.
This is particularly useful when your app needs to handle a high number of simultaneous requests.
By default, Upsun automatically sets a maximum number of PHP-FPM workers for your app.
This number is calculated based on three parameters:
- The container memory: the amount of memory you can allot for PHP processing
depending on [your defined application resources](/manage-resources.md).
- The request memory: the amount of memory an average PHP request is expected to require.
- The reserved memory: the amount of memory you need to reserve for tasks that aren't related to requests.
The number is calculated as follows: 
Note that when the resulting number is a decimal,
it's rounded up to set the maximum number of workers.
Also, the minimum number of PHP-FPM workers is 2.
To adjust the maximum number of PHP-FPM workers depending on your app's needs, follow the instructions on this page.
## Before you begin
You need:
- An up-and-running web app in PHP, complete with [PHP-FPM](https://www.php.net/manual/en/install.fpm.php)
- The [Upsun CLI](../../administration/cli/_index.md)
Note that the memory settings mentioned on this page are different from the [`memory_limit` PHP setting](./_index.md).
The `memory_limit` setting is the maximum amount of memory a single PHP process can use
before it's automatically terminated.
## 1. Estimate the optimal request memory for your app
To determine what the optimal request memory is for your app,
you can refer to your PHP access logs.
Run a command similar to:
```bash
upsun log --lines 5000 php.access | awk '{print $6}' | sort -n | uniq -c
```
This command takes into account the last 5,000 requests that reached PHP-FPM.
You can adjust this number depending on the amount of traffic on your site.
In the output, you can see how many requests used how much memory, in KB.
For example:
```bash
2654 2048
431 4096
584 8192
889 10240
374 12288
68 46384
```
The output shows that:
- The majority of requests peaked at 2,048 KB of memory.
- Most other requests used up to around 10 MB of memory.
- A few requests used up to around 12 MB of memory.
- Only 68 requests peaked at around 46 MB of memory.
In this situation, you might want to be cautious
and [set your request memory](#2-adjust-the-maximum-number-of-php-fpm-workers) to 12 MB.
Setting a lower request memory presents a risk of allowing more concurrent requests.
This can result in memory swapping and latencies.
## 2. Adjust the maximum number of PHP-FPM workers
By default, the request memory is set to 45 MB
and the reserved memory is set to 70 MB.
These values allow most programs to run,
but you can amend them to fit your needs.
To do so, adjust your [app configuration](../../create-apps/_index.md).
Under `runtime` in the [`sizing_hints` setting](/create-apps/app-reference/single-runtime-image.md#sizing-hints),
set the values for `reserved_memory` and `request_memory`.
For example,
if you estimate your [optimal request memory](#1-estimate-the-optimal-request-memory-for-your-app) to be 110 MB
and your reserved memory to be 80 MB,
you can use:
<--->
```yaml {configFile="app"}
applications:
myapp:
type: 'php:8.4'
runtime:
sizing_hints:
request_memory: 110
reserved_memory: 80
```
Note that the minimum value for the `request_memory` key is 10 MB
and the minimum value for the `reserved_memory` key is 70 MB.
If you set lower values,
they're automatically overridden with those minimums.
To check the maximum number of PHP-FPM workers available to your app,
run the following command, where `children` refers to PHP-FPM workers:
```bash
upsun ssh "grep -e '^pm.max_children' /etc/php/*/fpm/php-fpm.conf"
```
You get output similar to the following:
```bash
pm.max_children = 5
```
# Getting started with Upsun [Setup](https://docs.upsun.com/get-started/here/setup.html)
Got code?
In order to follow along with this guide, you need a local project.
While the guide has been written to accommodate the following stacks, it is not limited to just those listed and are here only as examples.
## Before you begin
You need:
- [Git](https://git-scm.com/downloads).
Git is the primary tool to manage everything your app needs to run.
Push commits to deploy changes and control configuration through YAML files.
These files describe your infrastructure, making it transparent and version-controlled.
- A Upsun account.
If you don't already have one, [register for a trial account](https://auth.upsun.com/register).
You can sign up with an email address or an existing GitHub, Bitbucket, or Google account.
If you choose one of these accounts, you can set a password for your Upsun account later.
- The [Upsun CLI](/administration/cli/_index.md).
This lets you interact with your project from the command line.
You can also do most things through the [Web Console](/administration/web/_index.md).
Trials
When you create your first organization on Upsun, you are also activating your trial for that organization.
Get more information on trials.
## Initialize your Git repository
A Git repository is required for Upsun projects.
If you haven't already done so, initialize a Git repository for your codebase, and commit your files:
```bash {location="Terminal"}
git init
git add .
git commit -m "Initial commit."
```
This guide assumes that your repository's default branch is `main`.
Your Git configuration may result in different default branches (like `master`), so please run `git branch -M main` before proceeding.
Don’t commit dependencies
Whether you’re migrating your own project, or testing Upsun with a starter project, never commit your app’s dependencies.
Make sure you ignore directories containing dependencies by updating your .gitignore file.
# Configure apps [Source operations](https://docs.upsun.com/create-apps/source-operations.html)
On Upsun, you can run automated code updates through a feature called **source operations**.
Defined in your [app configuration](./_index.md), source operations let you specify commands
that can commit changes to your project's repository when called.
For example, you can set up a source operation to [automatically update your application dependencies](/learn/tutorials/dependency-updates.md),
[update a site from an upstream repository](#update-a-site-from-an-upstream-repository-or-template),
or [revert to the last commit](#revert-to-the-last-commit) pushed to your Git repository.
To run your source operations, you can use the [Upsun CLI](../administration/cli/_index.md) or the [Console](https://console.platform.sh).
If you want to run your source operations and update your code automatically,
you can also define [cron jobs](/create-apps/app-reference/single-runtime-image.md#crons).
## How source operations work
When you trigger a source operation, the following happens in order:
1. The current environment HEAD commit is checked out in Git.
It doesn't have any remotes or tags defined in the project.
It only has the current environment branch.
2. Sequentially, for each app that has an operation bearing [the name](#define-a-source-operation)
of the triggered source operation in its configuration,
the operation command is run in the app container.
The container isn't part of the environment's runtime cluster
and doesn't require that the environment is running.
The environment has all of the variables normally available during the build phase.
These may be optionally overridden by the variables specified when the operation is run.
3. If any new commits were created, they're pushed to the repository and the normal build process is triggered.
If multiple apps in a single project both result in a new commit,
there are two distinct commits in the Git history but only a single new build process.
## Define a source operation
A source operation requires two things:
- A name that must be unique within the application.
The name is the key of the block defined under `source.operations` in your [app configuration](/create-apps/app-reference/single-runtime-image.md#source).
- A `command` that defines what's run when the operation is triggered.
The syntax is similar to the following:
```yaml {configFile="app"}
applications:
myapp:
type: nodejs:22
source:
root: "/"
operations:
SOURCE_OPERATION_NAME:
command: COMMAND
```
For example, to update a file from a remote location, you could define an operation like this:
```yaml {configFile="app"}
applications:
myapp:
type: nodejs:22
source:
root: "/"
operations:
update-file:
command: |
set -e
curl -O https://example.com/myfile.txt
git add myfile.txt
git commit -m "Update remote file"
```
The name of the source operation in this case is `update-file`.
For more possibilities, see other [source operation examples](#source-operation-examples).
## Run a source operation
Navigate to the environment where you want to run the operation.
Click More.
Click Run source operation.
Select the operation you want to run.
Optional: Add the variables required by your source operation.
Click Run.
Run the following command:
upsun source-operation:run SOURCE_OPERATION_NAME
Replace SOURCE_OPERATION_NAME with the name of your operation, such as update-file in the example above.
After running a source operation,
to apply the changes to your local development environment run the `git pull` command.
Note that you can [cancel pending or running source operations](../environments/cancel-activity.md).
## Use variables in your source operations
You can add [variables](../development/variables/_index.md) to the environment of the source operation.
Use the `env:` prefix to expose each of those variables as a Unix environment variable.
In this way, they're referenced by the source operation
and interpreted the same way as any other variable set in your project.
For example, you might want to have a `FILE` variable available with the value `example.txt`
to pass to a source operation similar to the following:
```yaml {configFile="app"}
applications:
myapp:
type: nodejs:22
source:
root: "/"
operations:
update-file:
command: |
set -e
curl -O https://example.com/$FILE
git add $FILE
git commit -m "Update remote file"
```
Follow these steps to run the source operation:
## Source integrations
If your project is using a [source integration](../integrations/source/_index.md),
any new commits resulting from a source operation are first pushed to your external Git repository.
Then the source integration pushes those commits to Upsun and redeploys the environment.
When using a source integration,
you can't run source operations on environments created from pull or merge requests created on the external repository.
If you try running a source operation on a non-supported environment, you see the following error:
```text
[ApiFeatureMissingException]
This project doesn't support source operations.
```
## Automated source operations using a cron job
You can use a cron to automatically run your source operations.
Note that it’s best not to run source operations on your production environment,
but rather on a dedicated environment where you can test changes.
Make sure you have the [Upsun CLI](../administration/cli/_index.md) installed
and [an API token](../administration/cli/api-tokens.md#2-create-an-api-token)
so you can run a cron job in your app container.
1. Set your API token as a top-level environment variable:
Open the environment where you want to add the variable.
Click Settings.
Click Variables.
Click + Add variable.
In the Variable name field, enter env:UPSUN_CLI_TOKEN.
In the Value field, enter your API token.
Make sure the Available at runtime and Sensitive variable options are selected.
Click Add variable.
Note
Once you add the API token as an environment variable,
anyone with SSH access can read its value.
Make sure you carefully check your user access on this project.
2. Add a build hook to your app configuration to install the CLI as part of the build process:
```yaml {configFile="app"}
applications:
myapp:
hooks:
build: |
set -e
echo "Installing Upsun CLI"
curl -fsSL https://raw.githubusercontent.com/platformsh/cli/main/installer.sh | bash
echo "Testing Upsun CLI"
upsun
```
3. Then, to configure a cron job to automatically run a source operation once a day,
use a configuration similar to the following:
```yaml {configFile="app"}
applications:
myapp:
type: nodejs:22
source:
root: "/"
operations:
update-file:
command: |
set -e
curl -O https://example.com/$FILE
git add $FILE
git commit -m "Update remote file"
crons:
update:
# Run the code below every day at midnight.
spec: '0 0 * * *'
commands:
start: |
set -e
upsun sync -e development code data --no-wait --yes
upsun source-operation:run update-file --no-wait --yes
```
The example above synchronizes the `development` environment with its parent
and then runs the `update-file` source operation defined [previously](#define-a-source-operation).
## Source operation examples
### Update your application dependencies
You can set up a source operation and a cron job to [automate your dependency updates](/learn/tutorials/dependency-updates.md).
### Update a site from an upstream repository or template
The following source operation syncronizes your branch with an upstream Git repository.
1. [Add a project-level variable](../development/variables/set-variables.md#create-project-variables)
named `env:UPSTREAM_REMOTE` with the Git URL of the upstream repository.
That makes that repository available as a Unix environment variable in all environments,
including in the source operation's environment.
- Variable name: `env:UPSTREAM_REMOTE`
- Variable example value: `https://github.com/platformsh/platformsh-docs`
2. In your app configuration, define a source operation to fetch from that upstream repository:
```yaml {configFile="app"}
applications:
myapp:
type: nodejs:22
source:
root: "/"
operations:
upstream-update:
command: |
set -e
git remote add upstream $UPSTREAM_REMOTE
git fetch --all
git merge upstream/main
```
3. Now every time you run the `upstream-update` operation on a given branch,
the branch fetches all changes from the upstream git repository
and then merges the latest changes from the default branch in the upstream repository.
If there’s a conflict merging from the upstream repository,
the source operation fails and doesn't update from the upstream repository.
Run the `upstream-update` operation on a preview environment rather than directly on Production.
### Revert to the last commit
The following source operation reverts the last commit pushed to the Git repository.
This can be useful if you didn't properly test the changes of another operation
and you need to quickly revert to the previous state.
```yaml {configFile="app"}
applications:
myapp:
type: nodejs:22
source:
root: "/"
operations:
revert:
command: |
git reset --hard HEAD~
```
Now every time you run the `revert` operation on a given branch,
the operation reverts to the last commit pushed to that branch.
### Update Drupal Core
The following source operation uses Composer to update Drupal Core:
```yaml {configFile="app"}
applications:
myapp:
type: php:8.4
source:
root: "/"
operations:
update-drupal-core:
command: |
set -e
composer update drupal/core --with-dependencies
git add composer.lock
git commit -m "Automated Drupal Core update."
```
`--with-dependencies` is used to also update Drupal Core dependencies.
Read more on how to [update Drupal Core via Composer on Drupal.org](https://www.drupal.org/docs/updating-drupal/updating-drupal-core-via-composer).
Now every time you run the `update-drupal-core` operation, it updates Drupal Core.
### Download a Drupal extension
The following source operation downloads a Drupal extension.
You can define the Drupal extension by setting an `EXTENSION` variable
or [overriding it](#use-variables-in-your-source-operations) when running the source operation.
```yaml {configFile="app"}
applications:
myapp:
type: php:8.4
source:
root: "/"
operations:
download-drupal-extension:
command: |
set -e
composer require $EXTENSION
git add composer.json
git commit -am "Automated install of: $EXTENSION via Composer."
```
Now every time you run the `download-drupal-extension` operation, it downloads the defined extension.
If it's a new extension, after the source operation finishes,
you need to enable the new extension via the Drupal management interface or using Drush.
### Update Git submodules
The following source operation updates all Git submodules recursively:
```yaml {configFile="app"}
applications:
myapp:
type: php:8.4
source:
root: "/"
operations:
rebuild:
command: |
set -e
git submodule update --init --recursive
git submodule update --remote --checkout
SHA=$(git submodule | awk -F' ' '{print $1}' | sed -s 's/+//g')
echo -n "$SHA" > .sha
git add uppler .sha
git commit -m "Updating submodule to commit '$SHA'"
```
Now every time you run the `rebuild` operation, it updates the Git submodules.
# Application metrics [Understanding application observablity](https://docs.upsun.com/increase-observability/application-metrics/understanding.html)
Multiple application observability features are available for your Upsun projects.
A full access to [Blackfire](https://www.blackfire.io/) is bundled with all your PHP and Python projects.
The continuous profiling of your NodeJS, Go, Ruby and Rust applications is available directly from the Console under the `Profiling` tab of your environments.
## Blackfire: Deterministic observability for PHP and Python
Blackfire has a **deterministic** approach for PHP and Python, meaning it collects an extensive range of metrics for every instrumented request or script.
The quantity of data and metrics collected differ for every layer of data Blackfire collects. The way scripts or requests are chosen to be instrumented also depends on the data layer.
[Profiles](https://blackfire.io/docs/profiling-cookbooks/index) are manually triggered by a Blackfire user, or automatically triggered by [Blackfire builds](https://blackfire.io/docs/builds-cookbooks/index), the synthetic monitoring feature that evaluates the performance of critical user journeys.
Meanwhile, monitoring traces and extended traces are based on the sample rate, which is the percentage of requests that are monitored. In that matter, [Blackfire monitoring](https://blackfire.io/docs/monitoring-cookbooks/index) offers a mix of two approaches:
- a probabilistic one on how requests are selected to be instrumented
- a deterministic one on how they are monitored, with the instrumentation starting at the very beginning of the request and ending with it
A [blog post](https://blog.blackfire.io/understanding-monitoring-traces-extended-traces-and-profiles.html) provides all the details on the differences and complementarity between Blackfire's monitoring traces, extended traces, and profiles.
## Continuous Profiling: Probabilistic observability
Probabilistic profiling involves capturing data intermittently. It collects information at defined intervals, logging functions or services activated by any ongoing request or script. This approach provides a more comprehensive view of your application’s performance over time, but certain event nuances may be overlooked due to the frequency of sampling.
Comparing deterministic to probabilistic profiling is akin to contrasting medical imaging devices. Asserting that an fMRI is unequivocally better than a PET scan or ultrasound is a misplaced judgment; each tool has its specific diagnostic purpose.
You might not know all the details about a specific script. But you will have a good overview of everything happening at a specific time. Information on shorter spans starting and ending between two consecutive ticks won’t be collected.
## Pros and cons
Both approaches have their strengths and weaknesses. One is not better than the other. It all depends on the instrumented languages and your understanding of the data.
- Deterministic profiling: Its strength lies in precision and facilitating meticulous script analysis. But it’s resource-intensive, leading to considerable overhead and potential data overload, making analysis potentially tedious.
- Probabilistic profiling: Lightweight and scalable, tailored for holistic application oversight. However, its periodic snapshots might miss rapid function calls, yielding a not-so-perfect application map.
Deterministic and probabilistic profiling each hold value within the development process. The former delivers a thorough and detailed view, while the latter offers a wider, more adaptable perspective. Developers may choose one or even combine both approaches based on the project’s specifics and the issues faced.# Development [Access your site](https://docs.upsun.com/development/access-site.html)
Once you have an environment running, you can view it in a web browser.
To find which URLs you can use to access your site, follow these steps:
Copy and paste any of these URLs into a web browser and access your site.
Run the following command:
upsun url
Select the URL to open in a browser.
For more information about URLs in your project and how you can control access to your web applications,
see how to [define routes](../define-routes/).
# Configure apps [Runtime operations](https://docs.upsun.com/create-apps/runtime-operations.html)
Runtime operations allow you to trigger one-off commands or scripts on your project.
Similar to [crons](/create-apps/app-reference/single-runtime-image.md#crons), they run in the app container but not on a specific schedule.
You can [define runtime operations](#define-a-runtime-operation) in your [app configuration](/create-apps/app-reference/single-runtime-image.md)
and [trigger them](#run-a-runtime-operation) at any time through the Upsun CLI.
For example, if you have a static website,
you may want to set up a runtime operation to occasionally fetch content from a backend system
without having to rebuild your whole app.
## Define a runtime operation
To define a runtime operation, add a configuration similar to the following:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
operations:
RUNTIME_OPERATION_NAME:
role: USER_ROLE
commands:
start: COMMAND
```
When you define a runtime operation,
you can specify which users can trigger it according to their user `role`:
- `viewer`
- `contributor`
- `admin`
If you don't set the `role` option when configuring your runtime operation,
by default all users with the `contributor` role can trigger it.
For example, to allow admin users to clear the cache of a Drupal site,
you could define an operation like the following:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
operations:
clear-rebuild:
role: admin
commands:
start: drush cache:rebuild
```
The name of the runtime operation in this case is `clear-rebuild`.
For more possibilities, see other [runtime operation examples](#runtime-operation-examples).
## Run a runtime operation
## List your runtime operations
To list all the runtime operations available on an environment,
run the following command:
```bash
upsun operation:list --project PROJECT_ID --environment ENVIRONMENT_NAME
```
## Runtime operation examples
### Build your app when using a static site generator
During every Upsun deployment, a standard [`build` step](/learn/overview/build-deploy.md#the-build) is run.
When you use a static site generator like Gatsby
or Next.js with a headless backend
you need to run a second `build` step to get your app ready for production.
This is because, as its framework is being built,
your frontend needs to pull content-related data from your backend’s API
(to generate all the static HTML pages your site is to serve).
To accomplish this on Upsun, where each app goes through a build-deploy pipeline in parallel,
your frontend’s build must be delayed _until after_ your backend has fully deployed.
It's often delayed up until the [`post_deploy` hook](../create-apps/hooks/hooks-comparison.md#post-deploy-hook) stage,
when the filesystem is read-only.
You can use a runtime operation to trigger the second `build` step
after the initial deployment of your app or after a redeployment.
You can also trigger it when you need to fetch content from your backend
but want to avoid going through the whole Upsun [build and deploy processes](/learn/overview/build-deploy.md) again.
Note
The following examples assume that the frontend and backend containers are included in the same environment.
This isn’t necessary for the commands to run successfully.
What is necessary is that the build destination for your frontend is writable at runtime
(meaning, you must define a mount for it).
If you don’t want to include a build within a mount (especially if your data source isn’t on Upsun),
you can use source operations to achieve a similar effect,
but through generating a new commit.
To run the Gatsby build step,
define a runtime operation similar to the following:
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"operations:gatsby-build:role:viewercommands:start:gatsby build
To trigger your runtime operation, run a command similar to the following:
To run the Next.js build step,
define a runtime operation similar to the following:
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"operations:next-build:role:admincommands:# All below are valid, depending on your setupstart:next build# start: npx next build# start: npm run build
To trigger your runtime operation, run a command similar to the following:
### Execute actions on your Node.js app
You can define runtime operations for common [pm2](https://pm2.io/docs/runtime/overview/) process manager tasks.
To ping your Node.js app, define a runtime operation similar to the following:
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"operations:pm2-ping:role:admincommands:start:| # Assuming pm2 start npm --no-daemon --watch --name $APP -- start -- -p $PORT
APP=$(cat package.json | jq -r '.name')
pm2 ping $APP
To trigger your runtime operation, run a command similar to the following:
To reload your Node.js app, define a runtime operation similar to the following:
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"operations:pm2-reload:role:admincommands:start:| # Assuming pm2 start npm --no-daemon --watch --name $APP -- start -- -p $PORT
APP=$(cat package.json | jq -r '.name')
pm2 reload $APP
To trigger your runtime operation, run a command similar to the following:
To restart your Node.js app, define a runtime operation similar to the following:
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"operations:pm2-restart:role:admincommands:start:| # Assuming pm2 start npm --no-daemon --watch --name $APP -- start -- -p $PORT
APP=$(cat package.json | jq -r '.name')
pm2 restart $APP
To trigger your runtime operation, run a command similar to the following:
### Define management commands on your Django project
On a Django project, you can [define custom `django-admin` commands](https://docs.djangoproject.com/en/4.2/howto/custom-management-commands/), for example to run a one-off management command (`manual migration` in the example above) outside of the Django ORM migration framework.
To do so, define a runtime operation similar to the following:
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
type: python:3.9
operations:
manual-migration:
role: admin
commands:
start: python manage.py manual_migration
```
To trigger your runtime operation, run a command similar to the following:
```bash
upsun operation:run manual-migration --project PROJECT_ID --environment ENVIRONMENT_NAME
```
# PHP [Using Xdebug](https://docs.upsun.com/languages/php/xdebug.html)
Note
You can now use composable image (BETA) to install runtimes and tools in your application container. To find out more, see the dedicated documentation page.
[Xdebug](https://xdebug.org/) is a real-time debugger extension for PHP.
While usually used for local development, it can also be helpful for debugging aberrant behavior on the server.
As configured on Upsun, it avoids any runtime overhead for non-debug requests, even in production, and only allows connections via SSH tunnels to avoid any security issues.
Note that Xdebug runs only on your app containers.
So you can't use it for [worker containers](../../create-apps/workers.md).
Also, note that if you use a [custom start command](./_index.md#alternate-start-commands),
Xdebug is automatically disabled.
## Before you begin
The following table shows the PHP versions where Xdebug is available:
5.4
5.5
5.6
7.0
7.1
7.2
7.3
7.4
8.0
8.1
8.2
8.3
8.4
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
Avail
You also need:
- The Upsun [CLI](../../administration/cli/_index.md)
- A Xdebug-compatible IDE installed on your machine.
For setup instructions, consult your IDE's Xdebug documentation, such as that for [PHPStorm](https://www.jetbrains.com/help/phpstorm/configuring-xdebug.html).
## 1. Set up Xdebug
Xdebug runs as a second PHP-FPM process used only for debugging requests, leaving the normal process unaffected.
To enable Xdebug, add the following to your [app configuration](/create-apps/app-reference/single-runtime-image.md):
```yaml {configFile="app"}
applications:
myapp:
type: 'php:8.4'
runtime:
xdebug:
idekey: YOUR_KEY
```
YOUR_KEY can be any arbitrary alphanumeric string.
When that key is defined, Upsun starts a second PHP-FPM process on the container that's identically configured but also has Xdebug enabled.
Only incoming requests that have an Xdebug cookie or query parameter set are forwarded to the debug PHP-FPM process.
All other requests are directed to the normal PHP-FPM process and thus have no performance impact.
If you have enabled the [router cache](../../define-routes/cache.md),
you need to explicitly add the Xdebug cookie (`XDEBUG_SESSION`) to the cookie allowlist.
Depending on the cookies already listed, the result should look similar to the following:
```yaml {configFile="routes"}
applications:
myapp:
type: 'php:8.4'
runtime:
xdebug:
idekey: YOUR_KEY
routes:
"https://{default}/":
# ...
cache:
enabled: true
cookies: ['/^SS?ESS/', 'XDEBUG_SESSION']
```
Xdebug has several configuration options available.
They can be set the same way as any other [PHP setting](./_index.md#php-settings).
For a full list of available options, consult the [Xdebug documentation](https://xdebug.org/docs/).
## 2. Use Xdebug
### Open a tunnel
To open an SSH tunnel to the server from a local checkout of your app, run the following [CLI command](../../administration/cli/_index.md) :
```bash
upsun environment:xdebug
```
That SSH tunnel allows your IDE and the server to communicate debug information securely.
By default, Xdebug operates on port `9003`.
Generally, it's best to configure your IDE to use that port.
To use an alternate port, use the `--port` flag.
To close the tunnel and terminate the debug connection, press Ctrl + C.
### Install an Xdebug helper
While Xdebug can be triggered from the browser by adding a special query parameter, the preferred way is to use a browser plugin helper.
Helpers are available for [Firefox](https://addons.mozilla.org/en-US/firefox/addon/xdebug-helper-for-firefox/)
and [Chrome](https://chrome.google.com/webstore/detail/xdebug-helper/eadndfjplgieldjbigjakmdgkmoaaaoc).
Their respective plugin pages document how to trigger them when needed.
## 3. Configure your IDE
Follow the instructions for your IDE, such as those for [PHPStorm](https://www.jetbrains.com/help/phpstorm/configuring-xdebug.html).
The common steps for setup usually include:
1. Configuring the Xdebug debug port and making sure it's set to the expected value (`9003` as default or the value you chose with `--port` when opening the tunnel).
2. Making sure that external connections are allowed.
3. Adding a new server for your Upsun environment.
The Host should be the hostname of the environment on Upsun you are debugging.
The Port should always be `443` and the Debugger set to `Xdebug`.
4. Ensuring path mappings is enabled.
This lets you define what remote paths on the server correspond to what path on your local machine.
In the majority of cases you can just define [your app root](/create-apps/app-reference/single-runtime-image.md#root-directory)
to map to `myapp`.
5. Listening for connections.
6. Starting debugging. While in listen mode, start the `upsun xdebug` tunnel.
Use the Xdebug helper plugin for your browser to enable debugging.
Set a break point in your app, then load a page in your browser.
The request should pause at the break point and allow you to examine the running app.
# PHP [Custom Redis versions](https://docs.upsun.com/languages/php/redis.html)
Note
You can now use composable image (BETA) to install runtimes and tools in your application container. To find out more, see the dedicated documentation page.
[Redis](../../add-services/redis.md) is a popular structured key-value service, supported by Upsun.
It's frequently used for caching.
## Install PhpRedis
The [PhpRedis](https://github.com/phpredis/phpredis) extension is available on Upsun's PHP container images.
The extension has been known to break its API between versions when removing deprecated functionality.
The version available on each application image is the latest available at the time that PHP version was built,
which if your app is sensitive to PhpRedis versions may not be ideal.
It may happen that the version of the PhpRedis extension available for your PHP version
isn't compatible with your app and upgrading your app isn't feasible.
If so, use the following script as an alternative to download and compile a precise version of the extension.
Note
Do not use this approach unless you really need to.
Using the provided PhpRedis extension is preferred in the majority of cases.
To ease the installation of a customer version of PhpRedis, use a [PhpRedis install script](https://github.com/platformsh/snippets/blob/main/src/install-phpredis.sh).
Invoke this script from your build hook, specifying a version.
Any tagged version of the library is acceptable:
```yaml {configFile="app"}
applications:
myapp:
type: 'php:8.4'
hooks:
build: |
set -e
# Install PhpRedis v5.3.7:
curl -fsS https://raw.githubusercontent.com/platformsh/snippets/main/src/install-phpredis.sh | { bash /dev/fd/3 5.3.7 ; } 3<&0
```
## Install Relay
Relay is a [Redis](../../add-services/redis.md) client
similar to [PhpRedis](https://github.com/phpredis/phpredis) and
[Predis](https://github.com/predis/predis).
It's intended to be a drop-in replacement for those libraries.
That PHP extension is also a shared in-memory cache like APCu. All retrieved keys are held in the PHP master process’ memory, which is shared across all FPM workers.
That means if the FPM Worker #1 fetches the `users:count` key from Redis,
all other FPM workers instantaneously retrieve that key from Relay without having to communicate with Redis.
To ease the installation of a customer version of Relay, use the [Relay install script](https://github.com/platformsh/snippets/blob/main/src/install-relay.sh).
Invoke this script from your build hook, specifying a version.
Any tagged version of the library is acceptable:
```yaml {configFile="app"}
applications:
myapp:
type: 'php:8.4'
hooks:
build: |
set -e
# Install Relay v0.6.0:
curl -fsS https://raw.githubusercontent.com/platformsh/snippets/main/src/install-relay.sh | { bash /dev/fd/3 v0.6.0 ; } 3<&0
```
## Change extension or version
To change the Redis extension or the version you are using, update the build hook and clear the build cache: `upsun project:clear-build-cache`.
The new version is *not* be used until you clear the build cache.
There's no need to declare the extension in the `runtime` block.
That's only for pre-built extensions.
## What these scripts do
1. Download the Relay/PhpRedis source code.
2. Check out the version specified in the build hook.
3. Compile the extension.
4. Copy the resulting `relay.so`/`redis.so` file to [your app root](/create-apps/app-reference/single-runtime-image.md#root-directory).
5. Add a line to the `php.ini` file in your app root to enable the extension, creating the file if necessary.
If the script doesn't find a `$PLATFORM_CACHE_DIR` directory defined, it exits silently.
So if you run the build hook locally, it has no effect.
# Development [Transfer files to and from your app](https://docs.upsun.com/development/file-transfer.html)
After your app is built, its file system is read-only.
This means that the only way you can edit your app's code is through Git.
However, you can transfer files to and from your built app without using Git.
To do so, you need to configure mounts or use an SSH client.
[Mounts](/create-apps/app-reference/single-runtime-image.md#mounts) let you set up directories that remain writable after the build is complete.
You can then transfer files directly to and from mounts inside your app
with a single command via the [Upsun CLI](../administration/cli/_index.md).
Alternatively, you can transfer files to and from your built app using an SSH client
such as `scp` or `rsync`.
## Transfer files using the CLI
### View the mounts inside your app
Before you start transferring files,
you may want to view a list of all the mounts inside your app.
To do so, run the following command:
```bash
upsun mounts
```
The output is similar to the following:
```bash
Mounts on abcdefgh1234567-main-abcd123--app@ssh.eu.upsun.com:
+-------------------------+----------------------+
| Mount path | Definition |
+-------------------------+----------------------+
| web/sites/default/files | source: storage |
| | source_path: files |
| private | source: storage |
| | source_path: private |
| tmp | source: tmp |
| | source_path: temp |
+-------------------------+----------------------+
```
### Transfer a file to a mount
To transfer a file to a mount using the CLI, you can use the `mount:upload` command.
For example, to upload the files contained in the local `private` directory to the `private` mount,
run the following command:
```bash
upsun mount:upload --mount private --source ./private
```
You get the following output:
```bash
Uploading files from ./private to the remote mount private
Are you sure you want to continue? [Y/n]
sending incremental file list
example.sh
sent 2.35K bytes received 20 bytes 1.58K bytes/sec
total size is 1.77M speedup is 745.09
```
### Transfer a file from a mount
To transfer a file from a mount using the CLI, you can use the `mount:download` command.
For example, to download a file from the `private` mount to your local `private` directory,
run the following command:
```bash
upsun mount:download --mount private --target ./private
```
You get the following output:
```bash
Downloading files from the remote mount private to ./private
Are you sure you want to continue? [Y/n]
receiving incremental file list
example.sh
sent 2.35K bytes received 20 bytes 1.58K bytes/sec
total size is 1.77M speedup is 745.09
```
## Transfer files using an SSH client
Another way to transfer files to and from your built app is to use an SSH client such as [`scp`](file-transfer.md#scp),
[`rsync`](file-transfer.md#rsync), or [`sftp`](file-transfer.md#sftp).
### scp
You can use `scp` to copy files to and from a remote environment.
For example, to download a `diagram.png` file from the `web/uploads` directory
(relative to the [app root](/create-apps/app-reference/single-runtime-image.md#root-directory)),
run the following command:
```bash
scp "$(upsun ssh --pipe)":web/uploads/diagram.png .
```
The `diagram.png` file is copied to the current local directory.
To copy files from your local directory to the Upsun environment,
reverse the order of the parameters:
```bash
scp diagram.png "$(upsun ssh --pipe)":web/uploads
```
For other options, see the [`scp` documentation](https://www.man7.org/linux/man-pages/man1/scp.1.html).
### rsync
You can use `rsync` to copy files to and from a remote environment.
For example, to copy all the files in the `web/uploads` directory on the remote environment
to the local `uploads` directory,
run the following command:
```bash
rsync -azP "$(upsun ssh --pipe)":web/uploads/ ./uploads/
```
To copy files from your local directory to the Upsun environment,
reverse the order of the parameters:
```bash
rsync -azP uploads/ "$(upsun ssh --pipe)":web/uploads/
```
Note that `rsync` is very sensitive about trailing `/` characters.
If you're using UTF-8 encoded files on macOS,
add the `--iconv=utf-8-mac,utf-8` flag to your `rsync` call.
For more options, consult the [rsync documentation](https://man7.org/linux/man-pages/man1/rsync.1.html).
### sftp
You can use `sftp` to copy files to and from a remote environment.
Note
Upsun supports sftp, but the following limitations apply:
You can only create sftp accounts with an existing Upsun user and an SSH key.
Custom users and passwords aren’t supported.
sftp access cannot be limited to a specific directory.
Instead, access is given to the whole application directory and its mounts.
#### Open an `sftp` connection
Run the following command:
```bash
sftp "$(upsun ssh --pipe)"
```
When prompted, select the project and environment you want to connect to.
The `sftp` connection is open once the `sftp>` prompt is displayed in your terminal.
#### Download a file
Say you want to download a `diagram.png` file from the `web/uploads` directory
(relative to the [app root](/create-apps/app-reference/single-runtime-image.md#root-directory)).
To do so, run the following command:
```
sftp> get web/uploads/diagram.png
```
The `diagram.png` file is copied to the current local directory.
#### Upload a file
Say you want to upload a `diagram.png` file to the `web/uploads` directory
(relative to the [app root](/create-apps/app-reference/single-runtime-image.md#root-directory)).
To do so, run the following command:
```bash
sftp> put diagram.png web/uploads
```
For other options, see the [`sftp` documentation](https://man7.org/linux/man-pages/man1/sftp.1.html).
# Development [HTTP Headers](https://docs.upsun.com/development/headers.html)
Upsun adds a number of HTTP headers to both inbound and outbound messages. We don’t modify or block existing headers on either request or response.
## Request headers
Upsun adds the following HTTP headers in the router to give the application information about the connection. These are stable and may be examined by the application as necessary.
* `X-Forwarded-Proto`: The protocol forwarded to the application, for example: `http`, `https`.
* `X-Client-IP`: The remote IP address of the request.
* `X-Client-SSL`: Set "on" only if the client is using SSL connection, otherwise the header isn't added.
* `X-Original-Route`: The route in `.upsun/config.yaml` which is used currently, for example: `https://{default}/`.
## Response headers
Upsun adds a number of response headers automatically to assist in debugging connections. These headers should be treated as a semi-private API. Do not code against them, but they may be inspected to help determine how Upsun handled the request to aid in debugging.
- `X-Platform-Cache`: Either `HIT` or `MISS` to indicate if the router in your cluster served the response from its own cache or if the request was passed through to the application.
- `X-Platform-Cluster`: The ID of the cluster that received the request. The cluster name is formed from the project ID and environment ID.
- `X-Platform-Processor`: The ID of the container that generated the response. The container ID is the cluster ID plus the container name.
- `X-Platform-Router`: The ID of the router that served the request. The router ID is the processor ID of the router container, specifically.
- `X-Debug-Info`: This is a header added by the edge layer. It doesn't contain any sensitive information or anything that could be misused. It has no relation to the PHP debugging tool [Xdebug](https://xdebug.org).
## Classification data headers
Upsun sends classification data to your backend system through the following HTTP headers.
| HTTP header | Type | Description |
| -------------------- | ------- | --------------------------------------------------------------------------------------------------------- |
| `Client-Cdn` | string | When a CDN that is supported by Upsun is used, this header displays its name (Fastly, Cloudflare, or Cloudfront). |
| `Client-Country` | string | The two-character ISO 3166-1 country code of the end-client IP (after CDN handling for the CDNs that Upsun supports). The geolocation data sent through this header is provided by [MaxMind GeoLite2](https://dev.maxmind.com/geoip/geolite2-free-geolocation-data).|
| `Client-Abuse-Score` | integer | The abuse score of the end-client IP. A score >= 100 indicates a near certainty that the request comes from an abusive IP. The abuse data sent through this header is provided by [AbuseIPDB](https://www.abuseipdb.com/). |
| `Client-Asn` | integer | The Autonomous System number of the end-client IP. The geolocation data sent through this header is provided by [MaxMind GeoLite2](https://dev.maxmind.com/geoip/geolite2-free-geolocation-data).|
## Custom headers
Apart from those listed above, your application is responsible for setting its own response headers.
You can also [add headers to static files](../create-apps/web/custom-headers.md).
# PHP [Swoole](https://docs.upsun.com/languages/php/swoole.html)
Note
You can now use composable image (BETA) to install runtimes and tools in your application container. To find out more, see the dedicated documentation page.
Swoole is a PHP extension that extends PHP core with a coroutine based asynchronous network application framework designed for building large scale concurrent systems.
Unlike PHP-FPM’s stateless operating, Swoole relies on establishing persistent connections with every user, sending and receiving data in real-time.
[Swoole](https://github.com/swoole/swoole-src) and [Open Swoole](https://openswoole.com/) are two forked libraries pursuing that goal.
Note
The swoole and openswoole extensions are available by default on Upsun PHP 8.2 Upsun containers.
For other versions of PHP, you can install both extensions manually by following the instructions on this page.
You need:
- PHP 7.3+ for Swoole
- PHP 7.4.0+ for Open Swoole
- The [Swoole installation script](https://raw.githubusercontent.com/platformsh/snippets/main/src/install_swoole.sh).
Note
Currently, the installation script is compatible with PHP <=8.0.It is not compatible with PHP 8.3,
and the swoole and openswoole extensions are not available on Upsun PHP 8.3 containers yet.
## Install
Install the PHP extension for Swoole or Open Swoole during the build.
Take advantage of an [installation script](https://raw.githubusercontent.com/platformsh/snippets/main/src/install_swoole.sh).
You need to pass 2 parameters:
* Which Swoole project to use: `openswoole` or `swoole`
* Which version to install
```yaml {configFile="app"}
applications:
app:
type: 'php:'
hooks:
build: |
set -e
...
curl -fsS https://raw.githubusercontent.com/platformsh/snippets/main/src/install_swoole.sh | { bash /dev/fd/3 openswoole 4.11.0 ; } 3<&0
```
## Use
Override the default web server with a [custom start command](./_index.md#alternate-start-commands).
Octane should listen on a TCP socket.
```yaml {configFile="app"}
applications:
myapp:
type: 'php:8.4'
web:
upstream:
socket_family: tcp
protocol: http
commands:
start: php PATH_TO_SWOOLE_START_COMMAND --port=$PORT
locations:
"/":
passthru: true
scripts: false
allow: false
```
# Consume logs [Access your logs](https://docs.upsun.com/increase-observability/logs/access-logs.html)
## Activity logs
Changes to your environments, such as deployments, cron jobs, and code or variable updates,
are each logged as activities.
You can access the logs either in the Console or using the [CLI](../../administration/cli/_index.md):
Click a recent activity from the activity feed or click All to see the complete history.
Get a list of activities by running
upsun activity:list -e ENVIRONMENT_NAME
Pass the --start flag to get activities from a specific date in the past.
To see details about the activity’s state and timing, run
upsun activity:get ACTIVITY_ID
Where ACTIVITY_ID comes from the list in step 1.
Get a log of any given activity by running
upsun activity:log ACTIVITY_ID
If a running activity is stuck, you can [cancel the activity](../../environments/cancel-activity.md).
### Sharing activity logs
When trying to identify and resolve failures, it can often help to have another person's perspective.
Troubleshoot collaboratively by sharing the logs of specific activities.
To share a log, open the log and click **Copy URL**.
Share specific lines in the log on clicking the line number.
To select multiple lines, hold Shift.
After selecting multiple lines,
hovering on the next unselected line gives you the amount of time that passed between the selected lines.

## Container logs
Events that occur within an app container are logged within that container.
The logs can be written to, but you should do so only with standard logging mechanisms.
If your app has its own logging mechanism, use it to write to a dedicated logs [mount](/create-apps/app-reference/single-runtime-image.md#mounts).
To access the logs of various types of events:
Use the upsun log command and specify the type of log you want.
For example, to get the access log, run:
upsun log -e ENVIRONMENT_NAME access
To get other logs, just replace access with the type of log.
To view more lines, use the --lines flag.
Access the container by running
upsun ssh -e ENVIRONMENT_NAME
Change to the right directory by running cd /var/log.
Read the desired log, such as by running tail access.log.
All log files are trimmed to 100 MB automatically.
If you need larger logs, set up a [cron job](/create-apps/app-reference/single-runtime-image.md#crons) to upload them to third-party storage.
See an example of [uploading logs to Amazon S3](https://gitlab.com/contextualcode/platformsh-store-logs-at-s3) from Contextual Code.
### Types of container logs
| Type | Always present | Description |
| ------------- | -------------- | ----------- |
| `access` | Yes | The raw access log for the nginx instance running on the container. It doesn't include requests that are redirected or cached by the [router](../../define-routes/_index.md). |
| `app` | Yes | All log messages generated by the app including language errors and exceptions. |
| `cron` | No | The output of cron jobs. Only exists after a cron job has run. |
| `deploy` | No | The output of the [`deploy` hook](../../create-apps/hooks/hooks-comparison.md#deploy-hook). Only exists after a `deploy` hook has run. |
| `dns` | Yes | All DNS queries made by processes in the container (such as the app and cron jobs). |
| `error` | Yes | nginx-level errors that occur once nginx has fully started such as HTTP errors for missing directories and excluded file types. |
| `nginx/error` | No | All nginx startup log messages. Only useful when debugging possible nginx configuration errors. Not currently available using the `upsun log` command. |
| `php.access` | No | A record of all requests to the PHP service. See [PHP access record format](#php-access-record-format). |
| `post-deploy` | No | The output of the [`post_deploy` hook](../../create-apps/hooks/hooks-comparison.md#post-deploy-hook). Only exists after a `post_deploy` hook has run. |
#### PHP access record format
The formatting of `php.access.log` is determined by the PHP settings.
To determine the format, run the following:
```bash
upsun ssh cat -n /etc/php/PHP_VERSION-zts/fpm/php-fpm.conf | grep "access.format"
```
You get a response such as the following:
```bash
Connection to ssh.eu.platform.sh closed.
access.format = "%{%FT%TZ}t %m %s %{mili}d ms %{kilo}M kB %C%% %{REQUEST_URI}e"
```
See what [each value in this string means](https://www.php.net/manual/en/install.fpm.configuration.php#access-format).
## Timezones
UTC is the default timezone for all logs.
# Development [Send email](https://docs.upsun.com/development/email.html)
You can configure your Upsun environments to send emails via an SMTP proxy.
Emails aren't guaranteed to be deliverable and you can't white-label them.
The SMTP proxy is intended as a zero-configuration, best-effort service.
Note
All preview environments are limited to 12,000 email credits per calendar month.
## 1. Turn on outgoing email
You can turn on outgoing email for each environment.
By default, email is turned on for your Production environment and blocked for other environments.
To turn it on for a specific environment, follow these steps:
To turn off outgoing email, replace true with false.
Changing the setting rebuilds the environment.
## 2. Recommended: Improve deliverability
Improve deliverability of your email with [Sender Policy Framework (SPF)](https://docs.sendgrid.com/ui/account-and-settings/spf-records).
If you don't have an SPF record, add the following `TXT` record to your domain's DNS records:
```txt
v=spf1 include:sendgrid.net -all
```
Having several, conflicting `TXT` records isn't supported due to [rfc4408 section 3.1.2](https://datatracker.ietf.org/doc/html/rfc4408#section-3.1.2).
If you already have an SPF record, please add SendGrid into your existing record.
## 3. (Optional) Validate your email
You can request for DomainKeys Identified Mail (DKIM) to be enabled on your domain.
DKIM improves your delivery rate as an email sender.
Learn more about [how DKIM works](https://docs.sendgrid.com/glossary/dkim).
To have DKIM enabled for your domain:
1. Open a [support ticket](/learn/overview/get-support) with the domain where you want DKIM.
2. Update your DNS configuration with the `CNAME` and `TXT` records that you get in the ticket.
Checks for the expected DNS records run every 15 minutes before validation.
The `TXT` record looks similar to the following:
```txt
v=spf1 include:u17504801.wl.sendgrid.net -all
```
## 4. Test the email service
To test the email service, use the [CLI](../administration/cli/_index.md) to connect to your app by running `upsun ssh`.
Run the following command:
```bash
printf "From: SENDER_EMAIL_ADDRESS\nSubject: Test \nThis is a test message" | /usr/sbin/sendmail RECIPIENT_EMAIL_ADDRESS
```
Replace the variables with actual email addresses as in the following example:
```bash
printf "From: someone@example.com\nSubject: Test \nThis is a test message" | /usr/sbin/sendmail someone@example.net
```
In a little while, the test message should arrive at the recipient address.
Be careful to test with real email addresses.
If you send emails to fake domains (such as `example.com`), they fail and hurt your sending reputation.
Make sure your test emails are deliverable.
## 5. Send email from your app
You can use `/usr/sbin/sendmail` on your app container to send emails as with the example in the previous step.
Or use the `PLATFORM_SMTP_HOST` environment variable in your SMTP configuration.
When outgoing emails are on, `PLATFORM_SMTP_HOST` is the address of the SMTP host that should be used.
When outgoing emails are off, the variable is empty.
When using `PLATFORM_SMTP_HOST`, send email through port 25 (often the default).
Your emails are proxied through the Upsun SMTP host and encrypted over port 465
before being sent to the outside world.
The precise way to send email depends on the language and framework you use.
See some examples for given languages.
To send email in PHP, you can use the built-in mail() function.
The PHP runtime is configured to send email automatically with the correct configuration.
This works even for libraries such as PHPMailer, which uses the mail() function by default.
Note that the From header is required.
Your email isn’t sent if that header is missing.
Beware of potential security problems when using the mail() function.
If you use any input from users in the $additional_headers or $additional_params parameters,
be sure to sanitize it first.
JavaMail is a Java API used to send and receive email via SMTP, POP3, and IMAP.
JavaMail is built into the Jakarta EE platform, but also provides an optional package for use in Java SE.
Jakarta Mail defines a platform-independent and protocol-independent framework to build mail and messaging applications.
The following example sends email using Jakarta Mail:
importsh.platform.config.Config;importjavax.mail.Message;importjavax.mail.MessagingException;importjavax.mail.Session;importjavax.mail.Transport;importjavax.mail.internet.InternetAddress;importjavax.mail.internet.MimeMessage;importjava.util.Properties;importjava.util.logging.Level;importjava.util.logging.Logger;publicclassJavaEmailSender{privatestaticfinalLoggerLOGGER=Logger.getLogger(JavaEmailSender.class.getName());publicvoidsend(){Configconfig=newConfig();Stringto="";//change accordinglyStringfrom="";//change accordinglyStringhost=config.getSmtpHost();//or IP address//Get the session objectPropertiesproperties=System.getProperties();properties.setProperty("mail.smtp.host",host);Sessionsession=Session.getDefaultInstance(properties);//compose the messagetry{MimeMessagemessage=newMimeMessage(session);message.setFrom(newInternetAddress(from));message.addRecipient(Message.RecipientType.TO,newInternetAddress(to));message.setSubject("Ping");message.setText("Hello, this is example of sending email ");// Send messageTransport.send(message);System.out.println("message sent successfully....");}catch(MessagingExceptionexp){exp.printStackTrace();LOGGER.log(Level.SEVERE,"there is an error to send an message",exp);}}}
## Alternative: Use a different email server
If you need more options, use your own SMTP server or email delivery service provider.
Bear in mind that TCP port 25 is blocked for security reasons.
Use port 465 or 587 instead to send email to your own external email server.
# YAML [{{% vendor/name %}} YAML tags](https://docs.upsun.com/learn/overview/yaml/platform-yaml-tags.html)
In addition to the [basic functions you should be familiar with](./what-is-yaml.md), YAML allows for special tags.
Upsun accepts certain custom tags to facilitate working with configuration files.
These tags work with Upsun configuration files, but may not elsewhere.
## Include
Use the `!include` tag to embed external files within a given YAML file.
The tag requires two properties:
| Property | Type | Possible values | Description |
| -------- | -------- | ----------------------------- | ----------- |
| `type` | `string` | `string`, `binary`, or `yaml` | See the descriptions of [strings](#string), [binaries](#binary), and [YAML](#yaml). Defaults to `yaml`. |
| `path` | `string` | | The path to the file to include, relative to the application directory or `source.root`. |
Note
By default, path is relative to the current application’s directory (what you would define with source.root).
It is possible to include files from a directory parent to the folder however.
### `string`
Use `string` to include an external file inline in the YAML file as if entered as a multi-line string.
For example, if you have a build hook like the following:
```yaml {configFile="app"}
applications:
myapp:
hooks:
build: |
set -e
cp a.txt b.txt
```
You could create a file for the script:
```text {location="build.sh"}
set -e
cp a.txt b.txt
```
And replace the hook with an include tag for an identical result:
```yaml {configFile="app"}
applications:
myapp:
hooks:
build: !include
type: string
path: build.sh
```
This helps you break longer configuration like build scripts out into a separate file for easier maintenance.
Even if ``path`` is relative to the current application's directory, it is also possible to include a shell script from a directory parent to the folder however.
For example, for the following project structure:
```bash
.
├── .upsun
| └── config.yaml
├── backend
│ ├── main.py
│ ├── requirements.txt
│ └── scripts
│ ├── ...
│ └── common_build.sh
└── frontend
├── README.md
├── package-lock.json
├── package.json
├── public
├── scripts
│ └── clean.sh
└── src
```
This configuration is valid:
```yaml {configFile="apps"}
applications:
frontend:
source:
root: frontend
# ...
hooks:
build: !include
type: string
path: ../backend/scripts/common_build.sh
```
Note
Please note that Upsun will execute this ../backend/scripts/common_build.sh script using Dash.
### `binary`
Use `binary` to include an external binary file inline in the YAML file.
The file is base64 encoded.
For example, you could include a `favicon.ico` file in the same folder as your app configuration.
Then you can include it as follows:
```yaml {configFile="app"}
some-property:
favicon: !include
type: binary
path: favicon.ico
```
### `yaml`
Use `yaml` to include an external YAML file inline as if entered directly.
Because `yaml` is the default, you can use it without specifying the type.
For example, you could have your configuration for works defined in a `worker.yaml` file:
```yaml {location="worker.yaml"}
commands:
start: python queue-worker.py
variables:
env:
type: worker
```
Then the following three configurations are exactly equivalent:
```yaml {configFile="app"}
workers:
queue1: !include "worker.yaml"
```
```yaml {configFile="app"}
workers:
queue1: !include
type: yaml
path: 'worker.yaml'
```
```yaml {configFile="app"}
workers:
queue1:
commands:
start: python queue-worker.py
variables:
env:
type: worker
```
This can help simplify more complex files.
For [multiple application](/create-apps/multi-app/_index.md) project, you can also include another ``.upsun/apps/my-app.yaml`` file in the main `.upsun/config.yaml`.
```yaml {location=".upsun/apps/my-app.yaml"}
source:
root: "/"
type: "nodejs:18"
web:
commands:
start: "node index.js"
upstream:
socket_family: tcp
locations:
"/":
passthru: true
```
and including it:
```yaml {configFile="apps"}
applications:
myapp:
!include ./apps/my-app.yaml
```
## Archive
Use the `!archive` tag for a reference to an entire directory specified relative to where the YAML file is.
For example, you might want to define a configuration directory for your [Solr service](/add-services/solr.md).
You might do so as follows:
```yaml {configFile="services"}
mysearch:
type: solr:8.0
configuration:
conf_dir: !archive "solr/conf"
```
The `!archive` tag means that the value for `conf_dir` isn't the string `solr/conf` but the entire `solr/conf` directory.
This directory is in the `.upsun` directory, since that's where the `.upsun/config.yaml` file is.
The `solr/conf` directory is then copied into the Upsun management system to use with the service.
# Application metrics [Blackfire for PHP and Python](https://docs.upsun.com/increase-observability/application-metrics/blackfire.html)
Full access to [Blackfire](https://www.blackfire.io/) is bundled with all your PHP and
Python Upsun projects.
Blackfire is the **official Upsun observability service** that helps you
improve the performance of your apps at each stage of their lifecycle.
With Blackfire's unique Application Performance Monitoring (APM), Profiling,
Alerting, and Testing features, you can achieve the following goals:
- Avoid performance bottlenecks by proactively identifying issues in your code
- Promptly solve identified issues by taking advantage of actionable recommendations
- Create performance budgets for critical parts of your app and get alerted of any
problem before a change hits your production
Blackfire is installed natively on Upsun and [works integrally with the Upsun workflow](https://www.youtube.com/watch?v=Bq-LFjgD6L0).
This results in an effortless setup process and smooth user experience.
## Get started with Blackfire
You can only access your Blackfire environments after you've been granted access to the related Upsun project.
Therefore, to access your Blackfire environments, make sure you log in using your Upsun account.
To access a Blackfire environment, each project user needs a Blackfire account.
When a project user doesn't already have a Blackfire account,
a new one is automatically created using the user's Upsun credentials.
### Automated integration
The Blackfire automated integration is enabled on your environments by default.
When you create a new environment,
it automatically triggers the creation of a Blackfire environment with the same settings.
On this Blackfire environment, you have access to [all the features provided by Blackfire](https://www.blackfire.io/features/).
This includes monitoring, profiling, alerting, and build-related features.
Note that Blackfire monitoring is enabled by default on your production environment.
On other environment types, you need to [enable it](#blackfire-monitoring).
User access settings are replicated from the Upsun Console to Blackfire -- this includes all [access levels](https://blackfire.io/docs/up-and-running/access-management).
You might have Blackfire variables already set on your project.
In this case, the existing variables override the settings of the automated integration.
Note
To trigger the synchronization of changes to users and their access levels,
you need to redeploy the environment.
### Blackfire monitoring
Blackfire monitoring is enabled by default on your production environment.
To enable Blackfire monitoring on your development or staging environments, follow these steps:
1. Go to your [organizations list](https://blackfire.io/my/organizations)
and select the organization where you want to enable Blackfire monitoring.
2. Click **Organization Monitoring Usage**.

3. In the **Monitoring Activation** section,
enable monitoring on the environments of your choice.

For more information on Blackfire monitoring features,
see the [Blackfire documentation](https://blackfire.io/docs/monitoring-cookbooks/index).
## Blackfire Profiling
While your code is running, the Blackfire profiler collects deep performance metrics
and provides full details and context of your code's behavior.
This helps you find the root cause of performance bottlenecks.
Blackfire lets you profile your application anywhere it's deployed,
including on your local development machines.
Using a browser extension or CLI command,
you can profile HTTP requests, CLI scripts, Consumers, and Daemons.
While HTTP requests can be profiled out-of-the-box, CLI profiling requires a
[specific configuration](https://blackfire.io/docs/integrations/paas/upsun#cli-profiling).
For more information on Blackfire profiling features,
see the [Blackfire documentation](https://blackfire.io/docs/profiling-cookbooks/index).
## Test the performance of each new deployment
Blackfire's native integration with Upsun enables you to test your app's performance
every time you deploy a branch in production, staging, or development.
Follow these steps:
1. Set up the [Blackfire Builds integration](https://blackfire.io/docs/integrations/paas/upsun#builds).
2. Optional: set up an [integration with your Git provider](https://blackfire.io/docs/integrations/git/index)
and get commit status updates from build reports.
3. Recommended: test business-critical use cases, with Blackfire [synthetic monitoring](https://blackfire.io/docs/builds-cookbooks/scenarios).
## Troubleshooting
### Bypass your reverse proxy, load balancer or CDN
To use [Blackfire profiling](#blackfire-profiling), you need to bypass any reverse
proxy, load balancer or [CDN](../../domains/cdn/_index.md) that sits in front of your app.
See [how to configure a bypass](https://blackfire.io/docs/reference-guide/reverse-proxies#documentation).
### Configure your HTTP cache
To take advantage of Blackfire features while using the HTTP cache with cookies,
allow the `__blackfire` cookie to go through the cache.
To do so, add [a configuration](../../define-routes/cache.md#allowing-only-specific-cookies)
similar to the following:
```yaml {configFile="routes"}
routes:
"https://{default}/":
cache:
enabled: true
cookies: ["/SESS.*/", "__blackfire"]
```
## Get support
If you're experiencing issues with Blackfire and [troubleshooting](#troubleshooting)
information doesn't help, follow these steps:
1. Retrieve [startup errors](#1-retrieve-startup-errors).
2. Retrieve your [Blackfire logs](#2-retrieve-your-blackfire-logs).
3. Send this data to [Blackfire Support](https://support.blackfire.io).
### 1. Retrieve startup errors
To retrieve startup errors, run the following command:
```bash
upsun ssh -- php -d display_startup_errors=on --ri blackfire
```
### 2. Retrieve your Blackfire logs
To retrieve your Blackfire logs, follow these steps:
1. On the environment where you're facing issues, create the following [variable](../../development/variables/set-variables.md):
```bash
upsun variable:create php:blackfire.log_file --value /tmp/blackfire.log
```
2. To set the verbosity of the logs to level 4 (debug level), create the following variable:
```bash
upsun variable:create php:blackfire.log_level --value 4
```
3. Start a profile or build.
4. To display the logs, run the following command:
```bash
upsun ssh -- cat /tmp/blackfire.log > blackfire.log
```
After you've retrieved the logs, you can disable them.
To do so, run the following commands:
```bash
upsun variable:delete php:blackfire.log_file
upsun variable:delete php:blackfire.log_level
```
# Set up multiple apps in a single project [Choose a project structure](https://docs.upsun.com/create-apps/multi-app/project-structure.html)
How you structure a project with multiple apps depends on how your code is organized
and what you want to accomplish.
For example, there are various ways you could set up the following multiple apps:
Here are some example use cases and potential ways to organize the project:
| Use case | Structure |
|-----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------|
| Separate basic apps that are worked on together. | [Unified app configuration](#unified-app-configuration) |
| One app depends on code from another app. | [Nested directories](#nested-directories) |
| You want to keep configuration separate from code, such as through Git submodules. | [Configuration separate from code](#split-your-code-source-into-multiple-git-submodule-repositories) |
| You want multiple apps from the same source code. | [Unified app configuration](#unified-app-configuration) |
| You want to control all apps in a single location. | [Unified app configuration](#unified-app-configuration) |
## Unified app configuration
You can configure all your apps from a single file.
To do so, create a `.upsun/config.yaml` and define each app as a key.
For example, if you have an API Platform backend with a Symfony API,
a Mercure Rocks server, and a Gatsby frontend,
you can organize your repository like this:
```txt
├── .upsun
│ ├── config.yaml <- Unified configuration
├── admin
│ └── ... <- API Platform Admin app code
├── api-app
│ └── ... <- Bigfoot app code
├── gatsby
│ └── ... <- Gatsby app code
└── mercure
└── ... <- Mercure Rocks app code
```
The `api` app is built from the `api-app` directory.
The `admin` app is built from the `admin` directory.
The `gatsby` app is built from the `gatsby` directory.
The `mercure` app is built from the `mercure` directory.
They all have different configurations for how they serve the files. For more details, see the [complete example file](https://github.com/platformsh-templates/bigfoot-multiapp/blob/multiapp-monolith/.platform/applications.yaml).
Note
The .upsun directory is located at the root, separate from your apps.
It contains all the needed configuration files to set up the routing, services and behavior of each app.
Since the code bases of your apps live in a different directory,
you need to change the source root of each app.
To build multiple apps from the repository root, set source.root to /.
This allows you to control all your apps in one place and even build multiple apps from the same source code.
To allow your apps to communicate with each other, define [relationships](./relationships.md).
Note that with this setup, when you amend the code of one of your apps,
the build image for your other apps can still be reused.
Once your repository is organized, you can use a configuration similar to the following:
```yaml {configFile="apps"}
applications:
api:
type: php:8.2
relationships:
database:
service: "database"
endpoint: "postgresql"
mounts:
"/var/cache": "shared:files/cache"
"/var/log": "shared:files/log"
"/var/sessions": "shared:files/sessions"
web:
locations:
"/":
root: "public"
passthru: '/index.php'
index:
- index.php
headers:
Access-Control-Allow-Origin: "*"
hooks:
build: |
set -x -e
curl -s https://get.symfony.com/cloud/configurator | bash
symfony-build
deploy: |
set -x -e
symfony-deploy
source:
root: api-app
admin:
type: nodejs:16
mounts:
'/.tmp_platformsh': 'shared:files/tmp_platformsh'
'/build': 'shared:files/build'
'/.cache': 'shared:files/.cache'
'/node_modules/.cache': 'shared:files/node_modules/.cache'
web:
locations:
"/admin":
root: "build"
passthru: "/admin/index.html"
index:
- "index.html"
headers:
Access-Control-Allow-Origin: "*"
hooks:
build: |
set -eu
corepack yarn install --immutable --force
post_deploy: |
corepack yarn run build
source:
root: admin
gatsby:
type: 'nodejs:18'
mounts:
'/.cache': { source: tmp, source_path: cache }
'/.config': { source: storage, source_path: config }
'/public': { source: storage, source_path: public }
web:
locations:
'/site':
root: 'public'
index: [ 'index.html' ]
scripts: false
allow: true
hooks:
build: |
set -e
yarn --frozen-lockfile
post_deploy: |
yarn build --prefix-paths
source:
root: gatsby
mercure:
type: golang:1.18
mounts:
'database': { source: storage, source_path: 'database' }
'/.local': { source: storage, source_path: '.local' }
'/.config': { source: storage, source_path: '.config' }
web:
commands:
start: ./mercure run --config Caddyfile.platform_sh
locations:
/:
passthru: true
scripts: false
request_buffering:
enabled: false
headers:
Access-Control-Allow-Origin: "*"
hooks:
build: |
# Install Mercure using cache
FILE="mercure_${MERCUREVERSION}_Linux_x86_64.tar.gz"
if [ ! -f "$PLATFORM_CACHE_DIR/$FILE" ]; then
URL="https://github.com/dunglas/mercure/releases/download/v${MERCUREVERSION}/$FILE"
wget -O "$PLATFORM_CACHE_DIR/$FILE" $URL
else
echo "Found $FILE in cache, using cache"
fi
file $PLATFORM_CACHE_DIR/$FILE
tar xvzf $PLATFORM_CACHE_DIR/$FILE
source:
root: mercure/.config
```
## Nested directories
When code bases are separate, changes to one app don't necessarily mean that the other apps in the project get rebuilt.
You might have a situation where app `main` depends on app `languagetool`, but `languagetool` doesn't depend on `main`.
In such cases, you can nest the dependency so the parent (`main`) gets rebuilt on changes to it or its children,
but the child (`languagetool`) is only rebuilt on changes to itself.
For example, you might have a Python app (`main`) that runs a script that requires Java code to be up to date.
But the Java app (`languagetool`) doesn't require updating when the Python app (`main`) is updated.
In that case, you can nest the Java app within the Python app:
```txt
├── .upsun
│ ├── .upsun/config.yaml
├── languagetool
│ └── main.java <- Java app code
└── main.py <- Python app code
```
The Python app's code base includes all of the files at the top level (excluding the `.upsun` directory)
*and* all of the files within the `languagetool` directory.
The Java app's code base includes only the files within the `languagetool` directory.
In this case, your `.upsun/config.yaml` file must contain 2 entries, one for the `main` app and second one for the `languagetool` app.
Note
The .upsun directory is located at the root, separate from your apps.
It contains all the needed configuration files to set up the routing, services and behavior of each app.
Since the code base of the languagetool app lives in a different directory (languagetool/),
you need to change the source root of the languagetool app.
Once your repository is organized, you can use a configuration similar to the following:
```yaml {configFile="apps"}
applications:
main:
type: 'python:3.11'
source:
root: '/'
...
languagetool:
type: 'java:17'
source:
root: 'languagetool'
...
```
## Split your code source into multiple Git submodule repositories
If you have different teams working on different code with different processes,
you might want each app to have its own repository.
Then you can build them together in another repository using [Git submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules).
With this setup, your apps are kept separate from the top application.
Each app has its own [Git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules) containing its code base.
All your apps are configured in a single `.upsun/config.yaml` file.
So you could organize your [project repository](https://github.com/platformsh-templates/bigfoot-multiapp/tree/submodules-root-app-yaml) like this:
```text
├── .upsun
│ ├── config.yaml
├── @admin <-- API Platform Admin submodule
├── @api <-- Bigfoot submodule
├── @gatsby <-- Gatsby submodule
├── @mercure <-- Mercure rocks submodule
└── .gitmodules
```
[Add the submodules using the Git CLI](/development/submodules.html#clone-submodules-during-deployment).
Your `.gitmodules` file would define all the submodules like this:
```txt {location=".gitmodules"}
[submodule "admin"]
path = admin
url = https://github.com/platformsh-templates/bigfoot-multiapp-admin.git
[submodule "api"]
path = api
url = https://github.com/platformsh-templates/bigfoot-multiapp-api.git
[submodule "gatsby"]
path = gatsby
url = https://github.com/platformsh-templates/bigfoot-multiapp-gatsby.git
[submodule "mercure"]
path = mercure
url = https://github.com/platformsh-templates/bigfoot-multiapp-mercure.git
```
Note
In this case, and any other case where your app configuration files are kept outside of the app directory,
make sure you change the source root for each of your apps.
## Change the source root of your app
When your app's code base and configuration file aren't located at the same directory level in your project repository,
you need to [define a root directory](/create-apps/app-reference/single-runtime-image.md#root-directory) for your app.
To do so, add a new `source.root` property in your app configuration.
For example, to change the source root of the `admin` app
from the [unified app configuration](#unified-app-configuration) example project,
you could add the following configuration:
```yaml {configFile="app"}
applications:
admin:
source:
root: admin
```
The `source.root` path is relative to the repository root.
In this example, the `admin` app now treats the `admin` directory as its root when building.
If `source.root` isn't specified, it defaults to the project root directory, that is `"/"`.
# Getting started with Upsun [Create a project](https://docs.upsun.com/get-started/here/create-project.html)
To create a new project on Upsun, you can take one of two paths:
Using the Console (recommended)
Open the [Upsun management console](https://console.upsun.com/-/create-project) to create your project.
Note
If you haven’t done so already, you are prompted to create your first organization where your project will reside.

From the Console, what you do next entirely depends on where the "source of truth" of your codebase is located.
In this guide, you will push your local repository to Upsun.
That is, the only copy of your codebase you'd like to deploy is on your local computer.
Click **Start from scratch** from the **Deploy with Git** option.
Git integrations
This guide does not specifically address integrating an Upsun project with a third party repository such as one on GitHub, even though the Connect repository option is available at this stage.
For now, continue to work locally.
Third party integrations will be addressed at the end of this guide.
Add details about your project, such as:
- The name of your project.
- The default branch of your local repository.
- Select the region where you want your project to be hosted.
As suggested in the Console, connect the local copy of your repository to your project:
```bash
upsun project:set-remote PROJECT_ID
```
Your local source code is automatically linked to your newly created Upsun project through the creation of a `.upsun/local/project.yaml` file. This file contains the corresponding `` and sets a Git remote to `upsun`.
Using the CLI
To create a new project with the Upsun CLI, use the following command and follow the prompts:
```bash {location="Terminal"}
upsun project:create
```
Default branches
When creating a new project using the Upsun CLI command project:create, the default production branch is set to main. Change it if your default branch is different (e.g.: master).
Then, you are asked if you want to set the local remote to your new project. Enter **Yes (y)**.
Your local source code is automatically linked to your newly created Upsun project through the creation of a `.upsun/local/project.yaml` file. This file contains the corresponding `` and sets a Git remote to `upsun`.
In this guide, you will push your local repository to Upsun.
That is, the only copy of your codebase you'd like to deploy is on your local computer.
Git integrations
This guide does not specifically address integrating an Upsun project with a third party repository such as one on GitHub, even though you will notice the Connect repository option available at this stage.
For now, continue to work locally.
Third party integrations will be addressed at the end of this guide.
So long as you chose `y` (yes) to the question `Set the new project as the remote for this repository?` during the `project:create` command, your local project is already integrated to the Upsun project.
# Consume logs [Forward {{% vendor/name %}} and Blackfire logs](https://docs.upsun.com/increase-observability/logs/forward-logs.html)
You might use a service to analyze logs from various parts of your fleet.
You might want to consolidate all your logs in one place that everyone has access to
without needing to grant them access to each project individually.
In such cases, forward your logs from Upsun and Blackfire to a third-party service.
You can use a [service with an integration](#use-a-log-forwarding-integration)
or any service that supports a [syslog endpoint](#forward-to-a-syslog-endpoint) or [HTTP endpoint](#forward-to-an-http-endpoint).
Logs to `stdout` and `stderr` are forwarded.
Logs in files can't be forwarded.
To enable log forwarding in a project, you need to be a [project admin](../../administration/users.md).
You also need your project to have the capability for log forwarding.
To get a price quote, [contact Sales](https://platform.sh/contact/).
## Use a log forwarding integration
Certain services have a specific integration for forwarding logs.
If your third-party service isn't supported, you can forward to a [syslog endpoint](#forward-to-a-syslog-endpoint).
### Integrated third-party services
Integrations exist for the following third-party services to enable log forwarding:
- [New Relic](https://newrelic.com/)
- [Splunk](https://www.splunk.com/)
- [Sumo Logic](https://www.sumologic.com/)
### Enable a log forwarding integration
#### Using the CLI
To enable log forwarding for a specific project using the [Upsun CLI](../../administration/cli/_index.md),
follow the steps for your selected service.
Get an API key from New Relic.
You need a license key.
Your New Relic organization likely has one, but you can create one by following the New Relic docs.
Choose an API endpoint.
You can use the U.S. endpoint https://log-api.newrelic.com/log/v1
or the EU endpoint https://log-api.eu.newrelic.com/log/v1.
Create the integration with the following command:
To start forwarding logs, [trigger a redeploy](../../development/troubleshoot.md#force-a-redeploy).
#### In the Console
To enable log forwarding for a specific project from the Console,
follow these steps:
1. Navigate to your project.
2. Click **Settings**.
3. Click **Integrations**.
4. Click **Add Integration**.
5. Select the integration you want to enable.
6. In the **Configure your integration** window,
specify your configuration options.
7. Click **Add Integration**.
The new integration overview is displayed,
and you can view your logs in the **Activity** section.
## Forward to a syslog endpoint
Syslog is a standard protocol for transferring log messages.
Many third-party services offer endpoints for ingesting syslog events.
You can forward your Upsun and Blackfire logs to any of those endpoints.
type, syslog-host, and syslog-port are the only properties required for all endpoints.
The following table shows the other available properties:
Property
Type
Default
Description
auth-token
string
The token to authenticate with the given service.
auth-mode
string
prefix
The mode for authentication with the given service. Can be prefix or structured_data. Defaults to prefix.
facility
string
1 (user)
A syslog facility code to attach with each log to identify the source. Can be a number from 0 to 23.
message-format
string
rfc5424
The standard to use for the message format. Can be rfc5424 or rfc3164.
protocol
string
tls
The network protocol to use in the connection. Can be one of tls, tcp, or udp. Defaults to tls.
verify-tls
boolean
true
Whether to verify Transport Layer Security (TLS) certification when using the TLS protocol.
To include a property, add it as a flag, for example --protocol tcp.
This should let you connect to any service that has syslog endpoints.
To start forwarding logs, once you’ve added the service trigger a redeploy.
To enable log forwarding to a syslog endpoint for a specific project using the Upsun CLI,
follow these steps:
Navigate to your project.
Click Settings.
Click Integrations.
Click Add Integration.
Select the syslog integration.
In the Configure your integration window,
specify your configuration options.
Click Add Integration.
The new integration overview is displayed,
and you can view your logs in the Activity section.
## Forward to an HTTP endpoint
Some third-party services, such as [Elasticsearch](../../add-services/elasticsearch.md) and [OpenSearch](../../add-services/opensearch.md),
support ingesting log messages through an HTTP endpoint.
You can use HTTP forwarding to forward Upsun and Blackfire logs to such third-party services.
HTTP forwarding makes a `POST` HTTP request with an `application/json` body while forwarding the log messages to the endpoint.
As an example, to forward logs to Elasticsearch using HTTP log forwarding, run the following command:
```
upsun integration:add --type httplog --url "https://ELASTICSEARCH_URL/INDEX_NAME/_doc" --header "Authorization: Basic " --header "Content-Type: application/json"
```
`type` and `url` are the only properties required for all endpoints.
Optionally, you can use the `headers` property to pass additional headers in the HTTP requests.
Note that if your endpoint URL includes a `PORT`, that can also be included in the `--url` flag:
```
upsun integration:add --type httplog --url "https://ELASTICSEARCH_URL:PORT/INDEX_NAME/_doc" --header "Authorization: Basic " --header "Content-Type: application/json"
```
Once you've [added the service](../../add-services/_index.md),
to start forwarding logs [trigger a redeploy](../../development/troubleshoot.md#force-a-redeploy).
## Log levels
Your app may output logs with distinct severity levels.
But as Plaform.sh only reads logs from `stdout`,
this distinction is lost and everything gets logged at `INFO` level.
To preserve the original log level, use a language-specific syslog module/package for logging.
The following example code snippets show how logs can be written to Syslog:
packagemainimport("fmt""log""log/syslog")funcmain(){syslogWriter,err:=syslog.Dial("","",syslog.LOG_LOCAL0|syslog.LOG_INFO,"")iferr!=nil{log.Fatal(err)}defersyslogWriter.Close()fmt.Fprintf(syslogWriter,"Operation has started")syslogWriter.Err("Operation failed")}
# Configure your project [JavaScript/Node.js](https://docs.upsun.com/get-started/here/configure/nodejs.html)
When dealing with Javascript/Node.js stacks, the information below may help customize your configuration.
These sections provide Javascript/Node.js-specific configuration details, but you can also refer to the common Upsun documentation:
- [Configuring applications](/create-apps)
- [Setting up managed services](/add-services)
- [Handling requests](/define-routes)
## Build flavors
By default, Upsun makes assumptions about how you want to build your application.
Namely, that you are managing your dependencies with npm, and that the very first thing you'd like to run is a particular and common production flavor of `npm install`.
This is called a build `flavor`, but its assumption may prove inappropriate for your application and cause your builds to fail (such as if you'd like to use yarn or bun instead of npm).
Therefore, you can [disable this feature](/languages/nodejs#dependencies).
## Available package managers
Certain package managers come pre-installed on all Upsun `nodejs` container types:
* *npm*; example: ``npm install platformsh-config``
* *npx*; example: ``npx create-strapi-app ``
* *bun*; example: ``bun install platformsh-config``
You can also use Yarn if you [install it explicitly](/languages/nodejs#use-yarn-as-a-package-manager), or [nvm](/languages/nodejs/node-version.md#use-nvm).
## Sample configuration
Below are some examples from common Node.js framework configuration:
applications:myapp:source:root:"/"type:"nodejs:20"web:commands:start:"npx next start -p $PORT"build:flavor:nonedependencies:nodejs:sharp:"*"#services:# db:# type: postgresql:15routes:"https://{default}/":type:upstreamupstream:"myapp:http"# A basic redirect definition# More information: https://docs.upsun.com/define-routes.html#basic-redirect-definition"https://www.{default}/":type:redirectto:"https://{default}/"
.upsun/config.yaml
applications:myapp:source:root:"/"type:"nodejs:20"web:commands:start:"node index.js"build:flavor:nonedependencies:nodejs:sharp:"*"#services:# db:# type: postgresql:14routes:"https://{default}/":type:upstreamupstream:"myapp:http"# A basic redirect definition# More information: https://docs.upsun.com/define-routes.html#basic-redirect-definition"https://www.{default}/":type:redirectto:"https://{default}/"
.upsun/config.yaml
applications:myapp:source:root:"/"type:"nodejs:20"relationships:postgresql:mounts:...web:commands:start:"NODE_ENV=production yarn start"build:flavor:nonedependencies:nodejs:yarn:"^1.22.0"hooks:build:| set -eux
yarn
yarn buildservices:postgresql:type:postgresql:15routes:"https://{default}/":type:upstreamupstream:"myapp:http"# A basic redirect definition# More information: https://docs.upsun.com/define-routes.html#basic-redirect-definition"https://www.{default}/":type:redirectto:"https://{default}/"
## Frameworks
The Upsun documentation includes a wide array of community resources to help with framework-specific configuration:
- [Express](/get-started/stacks/express)
- [Next.js](/get-started/stacks/nextjs)
- [Strapi](/get-started/stacks/strapi)
## Get support
While there are virtually no restrictions to you deploying any kind of application on Upsun, configuration may still be unclear at this point.
Not to worry! The Upsun community is here to help.
Come and say hello, share your work, ask for help, and peek in on what others are working on.
Welcome to the Upsun community!
# Development [Pull code from a private Git repository](https://docs.upsun.com/development/private-repository.html)
To complete its build, your Upsun project may need to access pieces of code stored in private Git repositories.
Examples include themes, libraries, and modules.
Configure these repositories to grant access to your project.
To grant access to a private Git repository,
add the project's public SSH key to your Git repository's deploy keys.
## 1. Get your project's public key
1. In the Console, open the project you want.
2. Click ** Settings**.
3. Under **Project settings**, click **Deploy key**.
4. Click ** Copy**.

## 2. Add the key to your repository in your Git provider
* [GitHub deploy key](https://docs.github.com/en/developers/overview/managing-deploy-keys#deploy-keys)
* [GitLab deploy key](https://docs.gitlab.com/ee/user/project/deploy_keys/#grant-project-access-to-a-public-deploy-key)
* [Bitbucket access key](https://support.atlassian.com/bitbucket-cloud/docs/configure-repository-settings/)
If you're only pulling code, the key doesn't need write permissions.
Now your Upsun project can access your private repository via SSH, including to add dependencies.
This means you can access the private repository through links like:
git@GIT_PROVIDER:PATH_OR_USERNAME/REPOSITORY.git.
For example, you can clone a repository in your [`build` hook](../create-apps/hooks/_index.md):
```yaml {configFile="app"}
applications:
APP_NAME:
hooks:
build: |
set -e
git clone git@bitbucket.org:username/module.git
```
You can also use [private repositories as submodules](./submodules.md#use-private-git-repositories).
## Using multiple private GitHub repositories
GitHub requires a separate deploy key for each repository.
To grant your project access to multiple repositories, create an automated user account, known as a machine user, with its own SSH key.
You can then add the machine account as collaborator to specific repositories
or to a team with access to the repositories.
See more information about [machine users on GitHub](https://docs.github.com/en/developers/overview/managing-deploy-keys#machine-users).
# Add services [RabbitMQ (message queue service)](https://docs.upsun.com/add-services/rabbitmq.html)
[RabbitMQ](https://www.rabbitmq.com/documentation.html) is a message broker
that supports multiple messaging protocols, such as the Advanced Message Queuing Protocol (AMQP).
It gives your apps a common platform to send and receive messages
and your messages a safe place to live until they're received.
## Supported versions
You can select the major and minor version.
Patch versions are applied periodically for bug fixes and the like.
When you deploy your app, you always get the latest available patches.
3.13
3.12
### Deprecated versions
The following versions are [deprecated](/glossary.html#deprecated-versions).
They're available, but they aren't receiving security updates from upstream and aren't guaranteed to work.
They'll be removed in the future,
so migrate to one of the [supported versions](#supported-versions).
3.11
3.10
3.9
3.8
3.7
3.6
3.5
## Relationship reference
For each service [defined via a relationship](#usage-example) to your application,
Upsun automatically generates corresponding environment variables within your application container,
in the ``$_`` format.
Here is example information available through the [service environment variables](/development/variables/_index.md#service-environment-variables) themselves,
or through the [``PLATFORM_RELATIONSHIPS`` environment variable](/development/variables/use-variables.md#use-provided-variables).
You can obtain the complete list of available service environment variables in your app container by running upsun ssh env.
Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the service environment variables directly rather than hard coding any values.
For some advanced use cases, you can use the PLATFORM_RELATIONSHIPS environment variable.
The structure of the PLATFORM_RELATIONSHIPS environment variable can be obtained by running upsun relationships in your terminal:
# Decode the built-in credentials object variable.exportRELATIONSHIPS_JSON=$(echo$PLATFORM_RELATIONSHIPS| base64 --decode)# Set environment variables for individual credentials.exportAPP_RABBITMQ_HOST="$(echo$RELATIONSHIPS_JSON| jq -r '.rabbitmq[0].host')"
## Usage example
### 1. Configure the service
To define the service, use the ``rabbitmq`` type:
```yaml {configFile="app"}
services:
# The name of the service container. Must be unique within a project.
:
type: rabbitmq:
```
Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service.
### 2. Define the relationship
To define the relationship, use the following configuration:
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<SERVICE_NAME>:
You can define <SERVICE_NAME> as you like, so long as it’s unique between all defined services
and matches in both the application and services configuration.
The example above leverages default endpoint configuration for relationships.
That is, it uses default endpoints behind-the-scenes, providing a relationship
(the network address a service is accessible from) that is identical to the name of that service.
With the above definition, the application container (<APP_NAME>) now has access to the service via the relationship <SERVICE_NAME> and its corresponding service environment variables.
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<RELATIONSHIP_NAME>:service:<SERVICE_NAME>endpoint:rabbitmq
You can define <SERVICE_NAME> and <RELATIONSHIP_NAME> as you like, so long as it’s unique between all defined services and relationships
and matches in both the application and services configuration.
The example above leverages explicit endpoint configuration for relationships.
applications:# The name of the app container. Must be unique within a project.myapp:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:rabbitmq>:services:# The name of the service container. Must be unique within a project.rabbitmq:type:rabbitmq:3.13
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:rabbitmq:service:rabbitmqendpoint:rabbitmqservices:# The name of the service container. Must be unique within a project.rabbitmq:type:rabbitmq:3.13
### Use in app
To use the configured service in your app, add a configuration file similar to the following to your project.
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"[...]# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:rabbitmq:services:# The name of the service container. Must be unique within a project.rabbitmq:type:rabbitmq:3.13
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"[...]# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:rabbitmq:service:rabbitmqendpoint:rabbitmqservices:# The name of the service container. Must be unique within a project.rabbitmq:type:rabbitmq:3.13
This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory.
`myapp` has access to the `rabbitmq` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship)
(as per [default endpoint](/create-apps/app-reference/single-runtime-image#relationships) configuration for relationships).
From this, ``myapp`` can retrieve access credentials to the service through the [relationship environment variables](#relationship-reference).
```bash {location="myapp/.environment"}
# Set environment variables for individual credentials.
# For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables.
export QUEUE_SCHEME=${RABBITMQ_SCHEME}
export QUEUE_USERNAME=${RABBITMQ_USERNAME}
export QUEUE_PASSWORD=${RABBITMQ_PASSWORD}
export QUEUE_HOST=${RABBITMQ_HOST}
export QUEUE_PORT=${RABBITMQ_PORT}
# Set a single RabbitMQ connection string variable for AMQP.
export AMQP_URL="${QUEUE_SCHEME}://${QUEUE_USERNAME}:${QUEUE_PASSWORD}@${QUEUE_HOST}:${QUEUE_PORT}/"
```
The above file — ``.environment`` in the ``myapp`` directory — is automatically sourced by Upsun into the runtime environment, so that the variable ``AMQP_URL`` can be used within the application to connect to the service.
Note that ``AMQP_URL``, and all Upsun [service environment variables](/development/variables/_index.md#service-environment-variables) like ``RABBITMQ_HOST``, are environment-dependent.
Unlike the build produced for a given commit,
they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment.
A file very similar to this is generated automatically for your when using the ``upsun ify`` command to [migrate a codebase to Upsun](/get-started/_index.md).
## Connect to RabbitMQ
When debugging, you may want to connect directly to your RabbitMQ service.
You can connect in multiple ways:
- An [SSH tunnel](#via-ssh)
- A [web interface](#access-the-management-ui)
In each case, you need the login credentials that you can obtain from the [relationship](#relationship-reference).
### Via SSH
To connect directly to your RabbitMQ service in an environment,
open an SSH tunnel with the [Upsun CLI](../administration/cli/_index.md).
To open an SSH tunnel to your service with port forwarding,
run the following command:
```bash
upsun tunnel:single --gateway-ports
```
Then configure a RabbitMQ client to connect to this tunnel using the credentials from the [relationship](#relationship-reference).
See a [list of RabbitMQ client libraries](https://www.rabbitmq.com/devtools.html).
### Access the management UI
RabbitMQ offers a [management plugin with a browser-based UI](https://www.rabbitmq.com/management.html).
You can access this UI with an SSH tunnel.
To open a tunnel, follow these steps.
1. SSH into your app container with a flag for local port forwarding:
2.
```bash
ssh $(upsun ssh --pipe) -L 15672:RELATIONSHIP_NAME.internal:15672
```
RELATIONSHIP_NAME is the [name you defined](#2-define-the-relationship).
2. Open `http://localhost:15672` in your browser.
Log in using the username and password from the [relationship](#relationship-reference).
## Configuration options
You can configure your RabbitMQ service in the [services configuration](#1-configure-the-service) with the following options:
| Name | Type | Required | Description |
|----------|-------------------|----------|------------------------------------------------------|
| `vhosts` | List of `string`s | No | Virtual hosts used for logically grouping resources. |
You can configure additional [virtual hosts](https://www.rabbitmq.com/vhosts.html),
which can be useful for separating resources, such as exchanges, queues, and bindings, into their own namespaces.
To create virtual hosts, add them to your configuration as in the following example:
```yaml {configFile="services"}
services:
# The name of the service container. Must be unique within a project.
rabbitmq:
type: "rabbitmq:3.13"
configuration:
vhosts:
- host1
- host2
```
## Upgrading
When upgrading RabbitMQ, skipping major versions (e.g. 3.7 -> 3.11) [is not supported](https://www.rabbitmq.com/upgrade.html#rabbitmq-version-upgradability).
Make sure you upgrade sequentially (3.7 -> 3.8 -> 3.9 -> 3.10 -> 3.11) and that each upgrade commit translates into an actual deployment.
# Administration [Server upgrades](https://docs.upsun.com/administration/servers.html)
Upsun runs a variety of servers to deliver its services.
To ensure your projects get the newest features, these servers are occasionally updated.
You don't have to do anything to get the updates.
When they're ready for your project, you see an activity about the server being updated in your [activity logs](../increase-observability/logs/access-logs.md#activity-logs).
These activities don't cause downtime for your project.
The log of the specific activity includes a description of what has changed with the update.
## Affected servers
### Project API server
The project API server responds to API calls to make the CLI and Console work for your project.
It acts as the Git server, mirroring the source repository in the case of [source integrations](../integrations/source/_index.md).
It stores your app code and project configuration, provides API interfaces,
and orchestrates the build and deploy process and other tasks for your environments.
### Project metrics server
The project metrics server retrieves information about your environments' use of RAM, CPU, and disk.
You can view this information as part of [environment metrics](../increase-observability/metrics/_index.md).
# Development [Use Git submodules](https://docs.upsun.com/development/submodules.html)
## Clone submodules during deployment
Upsun allows you to use submodules in your Git repository.
They're usually listed in a `.gitmodules` file at the root of your Git repository.
When you push via Git, Upsun tries to clone them automatically.
Say you have a multi-app project that includes the following submodules:
A BigFoot app
An API Platform v3, Admin component
A Gatsby frontend
A Mercure Rocks server
To import all the submodules, run the following commands from your multiple application project's root folder:
```bash
touch .gitmodules
git submodule add --name admin https://github.com/platformsh-templates/bigfoot-multiapp-admin.git admin
git submodule add --name api https://github.com/platformsh-templates/bigfoot-multiapp-api.git api
git submodule add --name gatsby https://github.com/platformsh-templates/bigfoot-multiapp-gatsby.git gatsby
git submodule add --name mercure https://github.com/platformsh-templates/bigfoot-multiapp-mercure.git mercure
git add .
git commit -m "Adding submodules for Bigfoot App, API Platform Admin, Gatsby frontend and Mercure Rocks server"
git push
```
Here is an example of a `.gitmodules` file:
```ini
[submodule "admin"]
path = admin
url = https://github.com/platformsh-templates/bigfoot-multiapp-admin.git
[submodule "api"]
path = api
url = https://github.com/platformsh-templates/bigfoot-multiapp-api.git
[submodule "gatsby"]
path = gatsby
url = https://github.com/platformsh-templates/bigfoot-multiapp-gatsby.git
[submodule "mercure"]
path = mercure
url = https://github.com/platformsh-templates/bigfoot-multiapp-mercure.git
```
When you run `git push`, you can see the output of the logs:
```bash
Validating submodules
Updating submodule ttps://github.com/platformsh-templates/bigfoot-multiapp-admin.git
Updated submodule https://github.com/platformsh-templates/bigfoot-multiapp-admin.git: 549 references updated.
Updating submodule ttps://github.com/platformsh-templates/bigfoot-multiapp-api.git
Updated submodule https://github.com/platformsh-templates/bigfoot-multiapp-api.git: 898 references updated.
Updating submodule https://github.com/platformsh-templates/bigfoot-multiapp-gatsby.git
Updated submodule https://github.com/platformsh-templates/bigfoot-multiapp-gatsby.git: 257 references updated.
Updating submodule https://github.com/platformsh-templates/bigfoot-multiapp-mercure.git
Updated submodule https://github.com/platformsh-templates/bigfoot-multiapp-mercure.git: 124 references updated.
...
```
When you amend your submodules’ code, make sure your changes are applied by running the following commands
before redeploying:
git submodule update --remote [submodule]Submodule path 'admin': checked out 'a020894cf94de6e79748890c942206bc7af752af'Submodule path 'api': checked out 'dce6617cc2db159c1a871112909e9ea4121135ec'Submodule path 'gatsby': checked out '012ab16b05f474278ad0f9916e1cb94fc9df5ba4'Submodule path 'mercure': checked out '94ccae5055983004aa8ab2c17b1daabd0c0a4927'
Note
To specify which submodule needs to be updated, replace [submodule] with your submodule path.
Automate your submodule updates using a source operation.
To do so, follow these steps:
Define a source operation.
Add the following configuration to your .upsun/config.yaml file:
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:source:operations:rebuild:command:| set -e
git submodule update --init --recursive
git submodule update --remote --checkout
git add admin api gatsby mercure
if ! git diff-index --quiet HEAD; then
git commit -m "Updating submodules admin, api, gatsby and mercure"
fi
For multiple app projects, make sure you define your source operation
in the configuration of an app whose source code is not in a submodule.
If you use Git submodules for each of your apps, define a new app at the top level of your project repository.
Don’t define routes so your app isn’t exposed to the web.
To define a source operation, add the following configuration to your app configuration:
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.update-submodule:# The type of the application to build.type:'nodejs:22'# The web key configures the web server running in front of your app.web:# Commands are run once after deployment to start the application process.commands:# The command to launch your app. If it terminates, it’s restarted immediately.# As this app will handle source operation only, no need to keep it alive (sleep)start:| sleep infinitysource:operations:update-submodules:command:| set -e
git submodule update --init --recursive
git submodule update --remote --checkout
git add .
if ! git diff-index --quiet HEAD; then
git commit -m "Updating submodules"
fi
# "git push" is automatic at the end of this command
Run your source operation.
To do so, in the Console,
navigate to the environment where you want to run the source operation.
Click More.
Click Run Source Operation.
Select the operation you want to run.
Click Run.
Alternatively, to run your source operation from the Upsun CLI,
run the following command:
upsun source-operation:run SOURCE_OPERATION_NAME
## Error when validating submodules
Using an SSH URL (`git@github.com:...`) to fetch submodules triggers the following error:
```bash
Validating submodules.
Found unresolvable links, updating submodules.
E: Error validating submodules in tree:
- admin: Exception: commit 03567c6 not found.
This might be due to the following errors fetching submodules:
- git@github.com:platformsh-templates/bigfoot-multiapp-admin.git: HangupException: The remote server unexpectedly closed the connection.
```
This is due to the fact that the Upsun Git server can't connect to GitHub via SSH without being granted an SSH key to do so.
To solve this issue, use an HTTPS URL (`https://github.com/...`) instead.
## Use private Git repositories
When using Git submodules that are private repositories, URLs with the HTTPS protocol fail with errors such as the following:
```bash
GitProtocolError: unexpected http resp 401 for https://bitbucket.org/myusername/mymodule.git/info/refs?service=git-upload-pack
```
To fix this, follow these steps:
1. Change your module declarations to use SSH for URLs.
Your existing declaration might look like this:
```bash {location=".gitmodules"}
[submodule "support/module"]
path = support/module
url = https://bitbucket.org/username/module.git
branch = submodule/branch
```
Change this to the following:
```bash {location=".gitmodules"}
[submodule "support/module"]
path = support/module
url = git@bitbucket.org:username/module.git
branch = submodule/branch
```
2. Add the [project's public key to your remote Git repository](./private-repository.md).
This allows your Upsun project to pull the repository from the remote Git service.
Note
Deploy keys only grant access to a single repository,
which can cause issues when attempting to pull several repositories to the same server.
If your server needs access to multiple repositories, follow these steps:
## Removing submodules
These steps aren't specific to Upsun, but kept as a reference for Git so that submodules are effectively removed before entering the build process.
1. In your `.gitmodules` and `.git/config` files, delete the information related to the submodule you want to remove.
```bash
git submodule deinit -f path_to_submodule
```
2. Stage changes to `.gitmodules`:
```bash
git add .gitmodules
```
3. Remove the submodule from the repository (without trailing slash):
```bash
git rm --cached path_to_submodule
```
4. Remove the submodule files in `.git` from the repository (without trailing slash):
```bash
rm -rf .git/modules/path_to_submodule
```
5. Commit the changes:
```bash
git commit -m "Removed submodule."
```
6. Remove the submodule code locally, now no longer tracked:
```bash
rm -rf path_to_submodule
```
# Development [Regions](https://docs.upsun.com/development/regions.html)
Upsun offers several regions for hosting project data.
You can choose a region based on criteria such as its closeness to your users and its environmental impact.
Upcoming changes!
On 17 March 2025, outbound IPs on all GCP and Azure regions will change.
These upcoming changes will affect outbound IPs for all GCP and Azure regions, and will require your intervention
if your are using public IP addresses explicitly.
Please see the documentation below for details and relevant deadlines.
## Environmental impact
At Upsun, we are committed to reducing our environmental impact. Whenever you create a project with us, we provide information about the electricity grid provider for that region. You can view the average carbon intensity of the energy grid in grams of CO2 equivalent per kilowatt-hour.
These data are sourced from an annual average, which we update as new information becomes available. If you want to see real-time emissions generated by each power grid, we recommend checking out [Electricity Maps](https://app.electricitymap.org/map). You can also access a public GitHub page of Electricity Maps [data sources](https://github.com/electricitymap/electricitymap-contrib/blob/master/DATA_SOURCES.md).
Summary of data being used in Upsun’s Region Picker when creating a new Project:
| Source | Last update of this page | Previous versions of this page |
|--------|--------------------------|--------------------------------|
| Electricity Maps 2022 annual averages (previous to May 2023, we had used annual averages from the IEA). See our [blog post](https://platform.sh/blog/platformsh-is-now-using-annual-carbon-intensities-from-electricity-maps/) for more information.| 11 May 2023 | Available [here](https://github.com/platformsh/platformsh-docs/commits/main/docs/src/development/regions.md) |
Information on carbon intensity is also available in the Upsun API.
For example, to get a list of the regions and their carbon intensities, run the following command:
```bash
upsun api:curl regions | jq -r '.regions[] | select(.available != false) | .label + ": " + .environmental_impact.carbon_intensity'
```
See all available information in the [API documentation](https://api.platform.sh/docs/#tag/Regions).
### Greener Region Discount
You can get a 3% discount on your resource usage if you host your project in one of Upsun's eco-friendly regions:
- Quebec, Canada (`ca-central-1`),
- Stockholm, Sweden (`eu-north-1`),
- Paris, France (`francecentral`),
- OVH (`gra7`),
- Quincy, Washington (`westus2`),
- Zurich, Switzerland (`europe-west6`).
The 3% discount covers application CPU, application memory, service CPU, service memory, and build resources.
It **doesn’t** apply to the project fee or other billing aspects.
It can be combined with other offers or discounts.
See [more information on the greener region discount](https://platform.sh/company/press/a-first-for-cloud-industry-platformsh-greener-region-discount/).
## Region availability
The regions listed here may be different from those available to you when you create a new project.
Each organization can have its own rules for what regions to allow.
When adding a new project, you only see regions allowed by your organization.
## Region location
To find out where a given region is hosted, use the following command:
``` bash
upsun api:curl regions | jq '.regions[] | select(.available != false) | .id + ": " + .provider.name + " - " + .zone + " - " + .timezone' | sort
```
The returned list contains, for each available region, its name, provider, geographic zone and its timezone.
## Public IP addresses
The public IP addresses for regions are stable, but not guaranteed to never change.
Before any change, you are notified well in advance regarding affected projects.
Planned and upcoming changes to IPs will be documented in the [**Upcoming changes**](#upcoming-changes) section below.
They're useful for cases such as when you have a corporate firewall that blocks outgoing SSH connections.
In such cases, add the inbound IP addresses for your region to your allow list.
## Regions
### Europe
## Upcoming changes
### GCP and Azure regions outbound IPs
On the 17th of March 2025, outbound IPs on **all GCP and Azure regions** will change.
Customer projects that refer to outbound IPs explicitly in their code and/or configuration must intervene and update to the **New outbound IPs** as soon as is possible.
Before the 17th of March, no traffic go through the **New outbound IPs**.
After the 17th of March, the **Old outbound IPs** will no longer be available.
Allowing both new and old IP addresses in any configuration during the transition period is recommended.
Region
Old outbound IPs
New outbound IPs
Region
United Kingdom (uk-1)
uk-1.platform.sh
Outbound ips
35.242.142.110
35.189.126.202
35.242.183.249
Outbound ips
35.246.36.142
34.147.217.161
34.89.33.176
Region
Germany (de-2)
de-2.platform.sh
Outbound ips
35.246.248.138
35.246.184.45
35.242.229.239
Outbound ips
34.159.207.210
34.159.181.149
34.107.79.7
Region
Switzerland (ch-1)
ch-1.platform.sh
Outbound ips
34.65.236.213
34.65.152.61
34.65.244.185
Outbound ips
34.65.197.163
34.65.144.16
34.65.72.28
Region
East (us-4)
us-4.platform.sh
Outbound ips
34.73.189.215
34.74.8.155
34.75.104.115
Outbound ips
104.196.203.234
34.148.171.57
35.243.131.172
Region
France (fr-4)
fr-4.platform.sh
Outbound ips
20.74.41.190
20.74.41.218
20.74.42.30
Outbound ips
20.188.46.156
20.188.46.158
20.188.46.165
Region
West (us-3)
us-3.platform.sh
Outbound ips
52.137.90.183
52.156.93.30
51.143.107.76
Outbound ips
52.148.128.255
52.250.13.106
40.91.69.215
Region
Australia (au-2)
au-2.platform.sh
Outbound ips
20.92.240.74
20.191.224.199
20.92.240.236
Outbound ips
104.210.116.116
40.126.245.226
104.210.117.92
#### How to audit the potential impact on an organization
You can determine which of your project are potentially impacted by this change via the CLI or the Console.
Navigate to the organization (ORG_NAME) you’d like to audit at https://console.upsun.com/ORG_NAME.
This view shows all of your projects within the organization ORG_NAME (assuming you have at least projects:list permissions on the organization).
On the left hand side, under the Filter heading, expand the Region option.
Under Region, select the following region filters:
Germany (de-2)
Switzerland (ch-1)
United Kingdom (uk-1)
United States - East (us-4)
France (fr-4)
United States - West (us-3)
Australia - East (au-2)
Not every project listed in this audit will necessarily be impacted by the change, only those that are explicitly using the outbound IPs in some way.
# Configure your project [PHP](https://docs.upsun.com/get-started/here/configure/php.html)
When dealing with PHP stacks, the information below may help customize your configuration.
These sections provide PHP-specific configuration details, but you can also refer to the common Upsun documentation:
- [Configuring applications](/create-apps)
- [Setting up managed services](/add-services)
- [Handling requests](/define-routes)
## Build flavors
By default, Upsun makes assumptions about how you want to build your application.
Namely, that you are managing your dependencies with Composer, and that the very first thing you'd like to run is a particular and common production flavor of `composer install`.
This is called a build `flavor`, but its assumption may prove inappropriate for your application and cause your builds to fail.
Therefore, you can [disable this feature](/languages/php#dependencies).
## Authenticated Composer
Packagist is the primary Composer repository for public PHP packages. But you can also have Composer download PHP packages from a private, third-party Composer repository. To make sure Composer has the necessary credentials to do so, follow the instructions on the [Authenticated Composer documentation](/languages/php/composer-auth).
## PHP settings
Upsun provides additional configuration possibilities to control:
- [PHP-FPM runtime configuration](/create-apps/app-reference/single-runtime-image#runtime)
- [PHP settings](/languages/php#php-settings)
## Enabling/disabling extensions
PHP has a number of extensions developed by members of the community.
Some of these extensions need to be enabled, while others are enabled by default and must be disabled if desirable.
See which [PHP extensions](/languages/php/extensions) are available for your version of PHP.
## Web servers
While PHP-FPM is the default behavior, Upsun provides some support for different web servers by modifying the `web.commands.start` property:
- [Alternate start commands](/languages/php#alternate-start-commands)
- [Swoole](/languages/php/swoole)
## Frameworks
The Upsun documentation includes a wide array of community resources to help with framework-specific configuration:
- [Laravel](/get-started/stacks/laravel)
- [Symfony](/get-started/stacks/symfony)
## Get support
While there are virtually no restrictions to you deploying any kind of application on Upsun, configuration may still be unclear at this point.
Not to worry! The Upsun community is here to help.
Come and say hello, share your work, ask for help, and peek in on what others are working on.
Welcome to the Upsun community!
# Development [Troubleshoot development](https://docs.upsun.com/development/troubleshoot.html)
## Common tasks
### Force a redeploy
There are times where you might want to trigger a redeployment of your application,
such as to add custom TLS certificates.
A redeploy reuses your built app and services.
To trigger a redeploy, follow these steps:
From the Environment menu, select the environment.
Click More.
Click Redeploy.
Run the following command:
upsun redeploy
The redeploy takes place after any scheduled activities (either *Running* or *Pending*).
Note
Despite the name, redeployment doesn’t rerun the deploy hook, only the post_deploy hook.
Both your build and deploy hooks are tied to individual commits in code.
They’re reused until another commit is pushed to the environment.
See more about hooks and their reuse.
Is there a way to redeploy the production environment without knowing its name?
It’s often desirable that the production environment, like many other values, is not hardcoded into your external workflows and management scripts.
You can use the CLI, along with the environment type distinction to identify a production environment (assuming there is only one) and redeploy it in a single line.
To do so, run the following command:
upsun redeploy -e $(upsun environment:list --type production --pipe)
### Manually trigger builds
To increase performance and keep applications the same across environments,
Upsun reuses built applications if its code and build time configuration (variables and such) remain the same.
There may be times where you want to force your application to be built again without changing its code,
for example to test an issue in a build hook or when external dependencies change.
To force a rebuild without changing the code,
use an [environment variable](./variables/set-variables.md#create-environment-specific-variables).
Assuming you want to do this for your `main` environment,
first create a `REBUILD_DATE` environment variable:
```bash
upsun variable:create --environment main --level environment --prefix env --name REBUILD_DATE --value "$(date)" --visible-build true
```
This triggers a build right away to propagate the variable.
To force a rebuild at any time, update the variable with a new value:
```bash
upsun variable:update --environment main --value "$(date)" "env:REBUILD_DATE"
```
This forces your application to be built even if no code has changed.
### Clear the build cache
You may find that you need to clear the build cache,
such as when it's grown too big or, in rare circumstances, when it's corrupted.
It may get corrupted when code is downloaded from a third-party language service like Packagist or npm
while that service is experiencing issues.
To clear the build cache, run the following command:
```sh
upsun project:clear-build-cache
```
The next build for each environment is likely to take longer as the cache rebuilds.
## Access denied or permission denied
In most cases, issues accessing a project are caused by missing permissions for a given user.
For more information see how to [manage user permissions](../administration/users.md).
If you are using the CLI, make sure that [you are authenticated](../administration/cli/_index.md#2-authenticate).
If you are using SSH, see how to [troubleshoot SSH access](../development/ssh/troubleshoot-ssh.md).
## HTTP responses 502 Bad Gateway or 503 Service Unavailable
If you see these errors when accessing your application,
it indicates your application is crashing or unavailable.
Typical causes and potential solutions include:
- Your app is listening at the wrong place.
- Check your app's [upstream properties](/create-apps/app-reference/single-runtime-image.md#upstream).
- If your app listening at a port, make sure it's using the [`PORT` environment variable](./variables/use-variables.md#use-provided-variables).
- Your `.upsun/config.yaml` configuration has an error and a process isn't starting
or requests can't be forwarded to it correctly.
- Check your `web.commands.start` entry or your `passthru` configuration.
- The amount of traffic coming to your site exceeds the processing power of your application.
- You may want to [check if bots are overwhelming your site](https://community.platform.sh/t/diagnosing-and-resolving-issues-with-excessive-bot-access/792).
- Certain code paths in your application are too slow and timing out.
- Check your code is running smoothly.
- Consider using the [observability solution](../increase-observability/application-metrics/_index.md) included in your project to get a better view of your application.
- A PHP process is crashing because of a segmentation fault.
- See [how to deal with crashed processes](../languages/php/troubleshoot.md#troubleshoot-a-crashed-php-process).
- A PHP process is killed by the kernel out-of-memory killer.
- See [how to deal with killed processes](../languages/php/troubleshoot.md#troubleshoot-a-killed-php-process).
## Site outage
If you can't access some part of your project, whether it's the live site, development environment, or Console,
check the [Upsun status page](https://status.platform.sh/).
There you can see planned maintenance and subscribe to updates for any potential outages.
If the status is operational, [contact support](/learn/overview/get-support.md).
## Command not found
When you've added a command line tool (such as [Drush](/glossary.md#drush)),
you might encounter an error like the following:
```bash
-bash: drush: command not found
```
If you see this, add the command you want to run to your path
with a [`.environment` file script](./variables/set-variables.md#set-variables-via-script).
As a Linux or Unix-like operating system user (MacOS included),
to be able to run your scripts directly and quickly get past this error
you may need to run the `chmod +x YOUR_SCRIPT_FILE_NAME` command.
However, regardless of which operating system you're using,
it's best if you **don't rely on scripts having execute permissions**.
Instead, call the app/shell/runtime directly passing your script file to that executable.
## Missing commits
If you push code to Upsun without the full Git history, sometimes commits are missing.
This can happen if you're pushing code from an external CI/CD pipeline, such as a GitHub action.
Such pipelines often do only shallow clones by default.
In such cases, your build might fail with an internal error.
Or you might see an error like `unexpected disconnect while reading sideband packet`.
To avoid the error, make sure you do a full clone of the repository before pushing code.
For example, for the [Checkout GitHub action](https://github.com/actions/checkout),
set `fetch-depth: 0` to clone the full history.
For GitLab, set clones to have a limit of `0` either in [repository settings](https://docs.gitlab.com/ee/ci/pipelines/settings.html#limit-the-number-of-changes-fetched-during-clone)
or using the [`GIT_DEPTH` variable](https://docs.gitlab.com/ee/user/project/repository/monorepos/index.html#shallow-cloning).
## Large JSON file upload failing
When trying to upload a large JSON file to your API, you might see a 400 response code (`Malformed request`).
Upsun enforces a 10 MB limit on files with the `application/json` `Content-Type` header.
To send large files, use the `multipart/form-data` header instead:
```bash
curl -XPOST 'https://example.com/graphql' --header 'Content-Type: multipart/form-data' --form file=large_file.json
```
## Databases
For MySQL specific errors, see how to [troubleshoot MySQL](../add-services/mysql/troubleshoot.md).
### Permission error creating a database
If you try to use a user to create a database, you get an error saying `permission denied to create database`.
The database is created for you and can be found in the `"SERVICE_NAME"_"PATH"` [service environment variable](./variables/_index.md#service-environment-variables),
or in the `path` key of the `PLATFORM_RELATIONSHIPS` [environment variable](./variables/use-variables.md#use-provided-variables).
## Storage
If you're having trouble with storage, see how to [troubleshoot mounts](../create-apps/troubleshoot-mounts.md) and [disks](../create-apps/troubleshoot-disks.md).
### Can't write to file system
If you attempt to write to disk outside a `build` hook, you may encounter a `read-only file system` error.
Except where you define it, the file system is all read-only, with code changes necessary through git.
This gives you benefits like repeatable deployments, consistent backups, and traceability.
To generate anything you need later, [write to disk during a `build` hook](/create-apps/app-reference/single-runtime-image.md#writable-directories-during-build).
Or [declare mounts](/create-apps/app-reference/single-runtime-image.md#mounts),
which are writable even during and after deploy.
They can be used for your data: file uploads, logs, and temporary files.
### Upsun push fails due to lack of disk space
You might see the following message when attempting to run `upsun push`:
`There isn't enough free space to complete the push`
This usually indicates that large files are present in the repository (where they shouldn't be).
Make sure that the paths for files like media files, dependencies, and databases are set to be ignored in your `.gitignore` file.
If large files are already in the repository, the open-source tool [bfg-repo-cleaner](https://rtyley.github.io/bfg-repo-cleaner/)
can help in cleaning up the repository by purging older commits, removing unnecessary files, and more.
If none of these suggestions work, open a [support ticket](/learn/overview/get-support).
## Stuck build or deployment
If you see a build or deployment running longer than expected, it may be one of the following cases:
- The build is blocked by a process in your `build` hook.
- The deployment is blocked by a long-running process in your `deploy` hook.
- The deployment is blocked by a long-running cron job in the environment.
- The deployment is blocked by a long-running cron job in the parent environment.
To determine if your environment is being stuck in the build or the deployment, check your [activity log](../increase-observability/logs/access-logs.md#activity-logs).
If the activity has the result `success`, the build has completed successfully and the system is trying to deploy.
If the result is still `running`, the build is stuck.
In most regions, stuck builds terminate after one hour.
When a deployment is blocked, you should try the following:
1. Connect to your environment using [SSH](./ssh/_index.md).
2. Find any long-running cron jobs or deploy hooks on the environment by running `ps afx`.
3. Kill any long-running processes with `kill PID`.
Replace `PID` with the process ID shown by `ps afx`.
If a `sync` of `activate` process is stuck, try the above on the parent environment.
Note that, for PHP apps,
you can [restart processes that get stuck during a build or deployment](../languages/php/troubleshoot.md#restart-php-processes-stuck-during-a-build-or-deployment)
from your app container.
## Slow or failing build or deployment
Builds can take long time or fail.
Most of the time, it's related to an application issue.
Here are a few tips that can help you find the exact cause.
### Check for errors in the logs
Invisible errors during the build and deploy phase can cause increased wait times, failed builds, and other problems.
Investigate [each log](../increase-observability/logs/access-logs.md#container-logs) and fix any errors you find.
### Build and deploy hooks
[`build` and `deploy` hooks](../create-apps/hooks/_index.md) can cause long build times.
If they run into issues, they can cause the build to fail or hang indefinitely.
`build` hooks can be tested in your local environment.
`deploy` hooks can be tested either locally
or by logging into the application over [SSH](./ssh/_index.md) and running them there.
Be careful not to test the scripts on production environments.
You can also test your hooks with these Linux commands to help debug issues:
```text
time YOUR_HOOK_COMMAND # Print execution time
strace -T YOUR_HOOK_COMMAND # Print a system call report
```
### Cron jobs
Containers can't be shutdown while long-running [cron jobs and scheduled tasks](/create-apps/app-reference/single-runtime-image.md#crons) are active.
That means long-running cron jobs block a container from being shut down to make way for a new deploy.
Make sure your custom cron jobs run quickly and properly.
Cron jobs may invoke other services in unexpected ways, which can increase execution time.
## Cache configuration
A common source of performance issues is a misconfigured cache.
The most common issue isn't allowing the right cookies as part of the router cache.
Some cookies, such as session cookies, need to be allowed.
Others, such as marketing and analytics cookies, usually shouldn't be part of the cache key.
See more about [router cache](../define-routes/cache.md)
and [cookie entry](../define-routes/cache.md#cookies).
Because the router cache follows cache headers from your app,
your app needs to send the correct `cache-control` header.
For static assets, set cache headers using the `expires` key in your [app configuration](/create-apps/app-reference/single-runtime-image.md#locations).
## Language-specific troubleshooting
For language-specific troubleshooting for your apps:
- [PHP](../languages/php/troubleshoot.md)
- [Node JS](../languages/nodejs/debug.md)
# Application metrics [Comparing Continuous Profiling Timeframes](https://docs.upsun.com/increase-observability/application-metrics/cont-prof-comparison.html)
Feature Availability
By default, Upsun offers 15 minutes of continuous profiling per project and for free.
To get 30 days of continuous profiling per project and for a fixed fee, upgrade to the Continuous Profiling add-on.
Upsun Continuous Profiler dashboard allows comparing two timeframes to better
understand application dynamics in various contexts.
You could compare two versions of the application, before and after a deployment,
or rush hours with quiet times for instance.
## Enabling comparison mode
A toggle on the top right corner of the continuous profiling dashboard enables
the comparison mode.

With comparisons enabled, you can select two timeframes referred to as ``A`` and
``B``. Those times can overlap.
## Understanding continuous profiling visual comparison
The flamegraph provides a visual representation of how timeframe ``B`` compares
to ``A`` for the selected dimension using shades of colors. The stronger the
color, the higher resource variation.

Shades of green indicates timeframe ``B`` is consuming less resources than ``A``
for the selected dimension. Shades of red indicate the opposite.
A scale and contextual information are displayed when hovering a span. This ensures
accessibility for all users and allow colorblind users to benefit from this feature.
# Application metrics [Continuous Profiling dashboard](https://docs.upsun.com/increase-observability/application-metrics/cont-prof.html)
Feature Availability
By default, Upsun offers 15 minutes of continuous profiling per project and for free.
To get 30 days of continuous profiling per project and for a fixed fee, upgrade to the Continuous Profiling add-on.
Continuous profiling is a multi-dimensional performance optimization technique
where web applications are monitored and profiled in real-time. Lightweight and
scalable, it's tailored for holistic application oversight.
Continuous profiling collects performance data continuously, enabling developers to
gain deep insights into their application's behavior, identify bottlenecks, and
optimize code for better performance and resource utilization. This proactive
approach allows for quicker identification and resolution of performance issues,
ensuring the smooth running of software in live environments.
## Continuous profiling on Upsun
Upsun Continuous Profiling is powered by [Blackfire](../../../increase-observability/application-metrics/blackfire.md).
It is available directly from the Console under the `Profiling` tab of your environments.
The Continuous Profiling dashboard lets you visualize the profiling data of a specific application.
It is composed of several views: flame graph, table view, and a split view combining the flame graph and table views.
Each view helps make sense of the profiling data for the selected dimension and time frame. The available dimensions vary with the runtime profiled.
## Color-coded node dimensions
Upsun continuous profiling dashboard employs a color-coded system to represent each dimension, ensuring consistency across different runtimes.
The intensity of a node's background color is directly proportional to the resources it consumes. As resource consumption increases, so does the vibrancy of the background color. This visual representation pinpoints application areas that may require optimization.

The contrast between the dimension color and the grayscale of regular nodes has been designed to ensure accessibility for all users and allow colorblind users to benefit from this feature.
## Flame graph
The flame graph is a hierarchical visualization of the contribution of the different function calls to the selected dimensions.
Flame graphs are effective in identifying performance issues and understanding the behavior of software during execution.

Rectangles in a flame graph are called frames. Each frame represents a function, arranged vertically (y-axis) to show the sequence of method calls.
The width of a frame relates to its resource usage. It helps pinpoint the most resource-intensive function calls. Their colors are not performance-related. They are meant to differentiate between functions.
Horizontally (x-axis), methods are sorted by name, not the order in which they run.
Hovering a frame displays in-depth information on it.

Clicking on a frame narrows down the flame graph to the callers and callee nodes of that frame.

## Table view
The table view displays a list of all the frames sorted by their resource consumption, for the selected dimension and time frame. By default, the table is sorted by `exclusive` resource consumption, which is the total value of the frame, minus the combined total values of its direct children.

# Set up multiple apps in a single project [Define routes for your multiple apps](https://docs.upsun.com/create-apps/multi-app/routes.html)
When you set up a project containing multiple applications,
all of your apps are served by a single [router for the project](/define-routes/_index.md).
Each of your apps must have a `name` that's unique within the project.
To define specific routes for one of your apps, use this `name`.
There are various ways you can define routes for multiple app projects.
In this project, you have a CMS app, two frontend apps (one using Symfony and another using Gatsby),
and a Mercure Rocks server app, defined as follows:
```yaml {configFile="apps"}
applications:
admin:
source:
root: admin
type: nodejs:22
api:
source:
root: api
type: php:8.4
gatsby:
source:
root: gatsby
type: nodejs:22
mercure:
source:
root: mercure/.config
type: golang:1.23
```
Note
You don’t need to define a route for each app in the repository.
If an app isn’t specified, then it isn’t accessible to the web.
One good example of defining an app with no route is when you use Git submodules and want to use a source operation to update your submodules.
You can also achieve the same thing by defining the app as a worker.
Depending on your needs, you could configure the router container
[using subdomains](#define-routes-using-subdomains) or using [subdirectories](#define-routes-using-subdirectories).
### Define routes using subdomains
You could define routes for your apps as follows:
```yaml {configFile="routes"}
routes:
"https://mercure.{default}/":
type: upstream
upstream: "mercure:http"
"https://{default}/":
type: upstream
upstream: "api:http"
```
So if your default domain is `example.com`, that means:
- `https://mercure.example.com/` is served by your Mercure Rocks app (`mercure`).
- `https://example.com/` is served by your Symfony frontend app (`api`).
Note
Using a subdomain might double your network traffic,
so consider using a path like https://{default}/api instead.
### Define routes using subdirectories
Alternatively, you could define your routes as follows:
```yaml {configFile="routes"}
routes:
"https://{default}/":
type: upstream
upstream: "api:http"
"https://{default}/admin":
type: upstream
upstream: "admin:http"
```
Then you would need to configure each app's `web.locations` property to match these paths:
```yaml {configFile="apps"}
applications:
admin:
source:
root: admin
type: nodejs:22
...
web:
locations:
'/admin':
passthru: '/admin/index.html'
root: 'build'
index:
- 'index.html'
api:
source:
root: api
type: php:8.4
...
web:
locations:
"/":
passthru: "/index.php"
root: "public"
index:
- index.php
routes:
"https://{default}/":
type: upstream
upstream: "api:http"
"https://{default}/admin":
type: upstream
upstream: "admin:http"
```
So if your default domain is `example.com`, that means:
- `https://example.com/` is served by your Symfony frontend app (`api`).
- `https://example.com/admin` is served by your Admin app (`admin`).
Note that in this example, for the configuration of your `admin` app,
you need to add the URL suffix `/admin` as both an index in the `web.locations` and a value for the `passhtru` setting.
For a complete example, [go to this project on GitHub](https://github.com/platformsh-templates/bigfoot-multiapp/tree/submodules-root-subfolders-applications).
# Configure your project [Python](https://docs.upsun.com/get-started/here/configure/python.html)
When dealing with Python stacks, the information below may help customize your configuration.
These sections provide Python-specific configuration details, but you can also refer to the common Upsun documentation:
- [Configuring applications](/create-apps)
- [Setting up managed services](/add-services)
- [Handling requests](/define-routes)
## Managing dependencies
Pip comes pre-installed in all `python` runtime containers.
With it, you can add `pip install` to your build hook and be well on your way to building your apps.
Alternatively, you can [use a different package manager](/languages/python/dependencies), such as Poetry or Pipvenv.
## Configuring web servers
Upsun doesn't enforce an assumption of what Python web server package you are using to serve your applications.
You can use any server on Upsun by modifying the `web.commands.start` property of your application configuration.
For more information, see how to [configure web servers](/languages/python/server).
## Frameworks
The Upsun documentation includes a wide array of community resources to help with framework-specific configuration:
- [Django](/get-started/stacks/django)
- [Flask](/get-started/stacks/flask)
## Get support
While there are virtually no restrictions to you deploying any kind of application on Upsun, configuration may still be unclear at this point.
Not to worry! The Upsun community is here to help.
Come and say hello, share your work, ask for help, and peek in on what others are working on.
Welcome to the Upsun community!
# Add services [Redis (Object cache)](https://docs.upsun.com/add-services/redis.html)
[Redis](https://redis.io/documentation) is a multi-model database that allows you to store data in memory
for high-performance data retrieval and key-value storage.
Upsun supports two different Redis configurations:
- [Persistent](#persistent-redis): to set up fast persistent storage for your application
- [Ephemeral](#ephemeral-redis): to set up a non-persistent cache for your application
## Supported versions
You can select the major and minor version.
Patch versions are applied periodically for bug fixes and the like.
When you deploy your app, you always get the latest available patches.
7.2
7.0
6.2
### Deprecated versions
The following versions are [deprecated](/glossary.html#deprecated-versions).
They're available, but they aren't receiving security updates from upstream and aren't guaranteed to work.
They'll be removed in the future,
so migrate to one of the [supported versions](#supported-versions).
6.0
5.0
4.0
3.2
3.0
2.8
Note that versions 3.0 and higher support up to 64 different databases per instance of the service,
while Redis 2.8 only supports a single database.
## Service types
Depending on your needs,
you can set up Redis as [persistent](#persistent-redis) or [ephemeral](#ephemeral-redis).
## Relationship reference
For each service [defined via a relationship](#usage-example) to your application,
Upsun automatically generates corresponding environment variables within your application container,
in the ``$_`` format.
Here is example information available through the [service environment variables](/development/variables/_index.md#service-environment-variables) themselves,
or through the [``PLATFORM_RELATIONSHIPS`` environment variable](/development/variables/use-variables.md#use-provided-variables).
You can obtain the complete list of available service environment variables in your app container by running upsun ssh env.
Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the service environment variables directly rather than hard coding any values.
For some advanced use cases, you can use the PLATFORM_RELATIONSHIPS environment variable.
The structure of the PLATFORM_RELATIONSHIPS environment variable can be obtained by running upsun relationships in your terminal:
# Decode the built-in credentials object variable.exportRELATIONSHIPS_JSON=$(echo$PLATFORM_RELATIONSHIPS| base64 --decode)# Set environment variables for individual credentials.exportAPP_REDIS_HOST="$(echo$RELATIONSHIPS_JSON| jq -r '.redis[0].host')"
The format of the relationship is identical whether your Redis service is [ephemeral](#ephemeral-redis) or [persistent](#persistent-redis).
## Persistent Redis
By default, Redis is an ephemeral service that stores data in memory.
This allows for fast data retrieval,
but also means data can be lost when a container is moved or shut down.
To solve this issue, configure your Redis service as persistent.
Persistent Redis stores data on a disk,
restoring it if the container restarts.
To switch from persistent to ephemeral Redis,
set up a new service with a different name.
Warning
Upsun sets the maximum amount of memory (maxmemory) Redis can use for the data set,
and it cannot be amended.
It is defined by comparing the following values and keeping the lower of the two:
The amount of memory allocated to the service container
For instance, if your Redis container has 3072 MB of disk space and 1024 MB of memory,
only 512 MB of RAM are actually available to the service (3072/6 = 512).
But if your Redis container has 3072 MB of disk space and 256 MB of memory,
only 256 MB of RAM are actually available to the service (as per the container limit).
### Usage example
#### 1. Configure the service
To define the service, use the `redis-persistent` endpoint:
```yaml {configFile="services"}
services:
# The name of the service container. Must be unique within a project.
:
type: redis-persistent:
```
Note that changing the name of the service replaces it with a brand new service and all existing data is lost.
Back up your data before changing the service.
#### 2. Define the relationship
To define the relationship, use the `redis` endpoint :
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<SERVICE_NAME>:
You can define <SERVICE_NAME> as you like, so long as it’s unique between all defined services and matches in both the application and services configuration.
The example above leverages default endpoint configuration for relationships. That is, it uses default endpoints behind-the-scenes, providing a relationship (the network address a service is accessible from) that is identical to the name of that service.
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<RELATIONSHIP_NAME>:service:<SERVICE_NAME>endpoint:redis
You can define <SERVICE_NAME> and <RELATIONSHIP_NAME> as you like, so long as it’s unique between all defined services and relationships
and matches in both the application and services configuration.
The example above leverages explicit endpoint configuration for relationships.
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# PHP extensions.runtime:extensions:- redis# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<SERVICE_NAME>:
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# PHP extensions.runtime:extensions:- redis# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<RELATIONSHIP_NAME>:service:<SERVICE_NAME>endpoint:redis
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:source:root:"myapp"[...]# PHP extensions.runtime:extensions:- redis# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:redis:services:# The name of the service container. Must be unique within a project.redis:type:redis-persistent:7.2
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:source:root:"myapp"[...]# PHP extensions.runtime:extensions:- redis# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:redis:service:redisendpoint:redisservices:# The name of the service container. Must be unique within a project.redis:type:redis-persistent:7.2
### Use in app
To use the configured service in your app, add a configuration file similar to the following to your project.
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:source:root:"myapp"# PHP extensions.runtime:extensions:- redis[...]# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:redis:services:# The name of the service container. Must be unique within a project.redis:type:redis-persistent:7.2
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:source:root:"myapp"# PHP extensions.runtime:extensions:- redis[...]# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:redis:service:redisendpoint:redisservices:# The name of the service container. Must be unique within a project.redis:type:redis-persistent:7.2
This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory.
`myapp` has access to the `redis` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship)
(as per [default endpoint](/create-apps/app-reference/single-runtime-image#relationships) configuration for relationships).
From this, ``myapp`` can retrieve access credentials to the service through the [relationship environment variables](#relationship-reference).
```bash {location="myapp/.environment"}
# Set environment variables for individual credentials.
# For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables.
export CACHE_HOST="${REDIS_HOST}"
export CACHE_PORT="${REDIS_PORT}"
export CACHE_PASSWORD="${REDIS_PASSWORD}"
export CACHE_SCHEME="${REDIS_SCHEME}"
# Surface a Redis connection string for use in app.
export CACHE_URL="${CACHE_SCHEME}://${CACHE_PASSWORD}@${CACHE_HOST}:${CACHE_PORT}"
```
The above file — ``.environment`` in the ``myapp`` directory — is automatically sourced by Upsun into the runtime environment, so that the variable ``CACHE_URL`` can be used within the application to connect to the service.
Note that ``CACHE_URL``, and all Upsun [service environment variables](/development/variables/_index.md#service-environment-variables) like ``REDIS_HOST``,
are environment-dependent.
Unlike the build produced for a given commit,
they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment.
A file very similar to this is generated automatically for your when using the ``upsun ify`` command to [migrate a codebase to Upsun](/get-started/_index.md).
## Ephemeral Redis
By default, Redis is an ephemeral service that serves as a non-persistent cache.
Ephemeral Redis stores data only in memory and requires no disk space.
When the service reaches its memory limit, it triggers a cache cleanup.
To customize those cache cleanups, set up an [eviction policy](#eviction-policy).
Make sure your app doesn't rely on ephemeral Redis for persistent storage as it can cause issues.
For example, if a container is moved during region maintenance,
the `deploy` and `post_deploy` hooks don't run and an app that treats the cache as permanent shows errors.
To prevent data from getting lost when a container is moved or shut down,
you can use the [persistent Redis](#persistent-redis) configuration.
Persistent Redis provides a cache with persistent storage.
### Usage example
#### 1. Configure the service
To define the service, use the `redis` endpoint:
```yaml {configFile="services"}
services:
# The name of the service container. Must be unique within a project.
:
type: redis:
```
Note that changing the name of the service replaces it with a brand new service and all existing data is lost.
Back up your data before changing the service.
#### 2. Define the relationship
To define the relationship, use the `redis` endpoint :
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<SERVICE_NAME>:
You can define <SERVICE_NAME> as you like, so long as it’s unique between all defined services and matches in both the application and services configuration.
The example above leverages default endpoint configuration for relationships. That is, it uses default endpoints behind-the-scenes, providing a relationship (the network address a service is accessible from) that is identical to the name of that service.
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<RELATIONSHIP_NAME>:service:<SERVICE_NAME>endpoint:redis
You can define <SERVICE_NAME> and <RELATIONSHIP_NAME> as you like, so long as it’s unique between all defined services and relationships
and matches in both the application and services configuration.
The example above leverages explicit endpoint configuration for relationships.
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:source:root:"myapp"[...]# PHP extensions.runtime:extensions:- redis# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<SERVICE_NAME>:services:# The name of the service container. Must be unique within a project.<SERVICE_NAME>:type:redis:<VERSION>
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:source:root:"myapp"[...]# PHP extensions.runtime:extensions:- redis# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<RELATIONSHIP_NAME>:service:<SERVICE_NAME>endpoint:redisservices:# The name of the service container. Must be unique within a project.<SERVICE_NAME>:type:redis:<VERSION>
applications:# The name of the app container. Must be unique within a project.myapp:source:root:"myapp"[...]# PHP extensions.runtime:extensions:- redis# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:redis:services:# The name of the service container. Must be unique within a project.redis:type:redis:7.2
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:source:root:"myapp"[...]# PHP extensions.runtime:extensions:- redis# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:redis:service:redisendpoint:redisservices:# The name of the service container. Must be unique within a project.redis:type:redis:7.2
### Use in app
To use the configured service in your app, add a configuration file similar to the following to your project.
applications:# The name of the app container. Must be unique within a project.myapp:source:root:"myapp"[...]# PHP extensions.runtime:extensions:- redis# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:redis:services:# The name of the service container. Must be unique within a project.redis:type:redis:7.2
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:source:root:"myapp"[...]# PHP extensions.runtime:extensions:- redis# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:redis:service:redisendpoint:redisservices:# The name of the service container. Must be unique within a project.redis:type:redis:7.2
This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory.
`myapp` has access to the `redis` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship)
(as per [default endpoint](/create-apps/app-reference/single-runtime-image#relationships) configuration for relationships).
From this, ``myapp`` can retrieve access credentials to the service through the [relationship environment variables](#relationship-reference).
```bash {location="myapp/.environment"}
# Set environment variables for individual credentials.
# For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables.
export CACHE_HOST="${REDIS_HOST}"
export CACHE_PORT="${REDIS_PORT}"
export CACHE_PASSWORD="${REDIS_PASSWORD}"
export CACHE_SCHEME="${REDIS_SCHEME}"
# Surface a Redis connection string for use in app.
export CACHE_URL="${CACHE_SCHEME}://${CACHE_PASSWORD}@${CACHE_HOST}:${CACHE_PORT}"
```
The above file — ``.environment`` in the ``myapp`` directory — is automatically sourced by Upsun into the runtime environment, so that the variable ``CACHE_URL`` can be used within the application to connect to the service.
Note that ``CACHE_URL``, and all Upsun [service environment variables](/development/variables/_index.md#service-environment-variables) like ``REDIS_HOST``,
are environment-dependent.
Unlike the build produced for a given commit,
they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment.
A file very similar to this is generated automatically for your when using the ``upsun ify`` command to [migrate a codebase to Upsun](/get-started/_index.md).
## Multiple databases
Redis 3.0 and above support up to 64 databases.
But you can't set up different access rights to each database.
When you set up a relationship connection,
access to all of the databases is automatically granted.
The way to access a particular database depends on the [client library](https://redis.io/clients) you're using:
<?php$redis=newRedis();$redis->connect(getenv('REDIS_HOST'),getenv('REDIS_PORT'));$redis->select(0);// switch to DB 0
$redis->set('x','42');// write 42 to x
$redis->move('x',1);// move to DB 1
$redis->select(1);// switch to DB 1
$redis->get('x');// returns 42
To manage thread safety,
the Python library suggests using separate client instances for each database:
constredis=require('redis');constclient=redis.createClient(process.env.REDIS_PORT,process.env.REDIS_HOST);awaitclient.SELECT(0);// switch to DB 0
awaitclient.set('x','42');// write 42 to x
awaitclient.MOVE('x',1);// move to DB 1
awaitclient.SELECT(1);// switch to DB 1
constvalue=awaitclient.get('x');// returns 42
## Eviction policy
When Redis reaches its memory limit,
it triggers a cache cleanup.
To customize those cache cleanups, set up an eviction policy such as the following:
```yaml {configFile="services"}
services:
# The name of the service container. Must be unique within a project.
redis:
type: "redis:7.2"
configuration:
maxmemory_policy: allkeys-lfu
```
The following table presents the possible values:
| Value | Policy description |
|-------------------|-------------------------------------------------------------------------------------------------------------|
| `allkeys-lru` | Removes the oldest cache items first. This is the default policy when `maxmemory_policy` isn't set. |
| `noeviction` | New items aren’t saved when the memory limit is reached. |
| `allkeys-lfu` | Removes least frequently used cache items first. |
| `volatile-lru` | Removes least recently used cache items with the `expire` field set to `true`. |
| `volatile-lfu` | Removes least frequently used cache items with the `expire` field set to `true`. |
| `allkeys-random` | Randomly removes cache items to make room for new data. |
| `volatile-random` | Randomly removes cache items with the `expire` field set to `true`. |
| `volatile-ttl` | Removes cache items with the `expire` field set to `true` and the shortest remaining `time-to -live` value. |
For more information on the different policies,
see the official [Redis documentation](https://redis.io/docs/reference/eviction/).
## Access your Redis service
After you've [configured your Redis service](#usage-example),
you can access it using either the Upsun CLI
or through the [Redis CLI](https://redis.io/docs/ui/cli/).
### Upsun CLI
Unlike the Redis CLI, connecting via the Upsun CLI does not require additional authentication steps if you are already authenticated in your terminal.
Access your Redis service by running the command:
```bash
upsun redis
```
### Redis CLI
Retrieve the hostname and port you can connect to
through the `PLATFORM_RELATIONSHIPS` [environment variable](../../development/variables/use-variables.md#use-provided-variables).
To do so, run the `upsun relationships` command.
After you've retrieved the hostname and port, [open an SSH session](../development/ssh/_index.md).
To access your Redis service, run the following command:
```bash
redis-cli -h HOSTNAME -p PORT
```
If you have a Grid project, note that the `CONFIG GET` and `CONFIG SET` admin commands are restricted.
To get the current configuration, run the following command:
```bash
redis-cli -h HOSTNAME -p PORT info
```
## Use Redis as a handler for PHP sessions
A PHP session allows you to store different data for each user through a unique session ID.
By default, PHP handles sessions using files.
But you can use Redis as a session handler,
which means Redis stores and retrieves the data saved into sessions.
To set up Redis as your session handler, add a configuration similar to the following:
applications:# The name of the app container. Must be unique within a project.myapp:source:root:"myapp"type:"php:8.4"# PHP extensions.runtime:extensions:- redisrelationships:redissession:variables:php:session.save_handler:redissession.save_path:"tcp://$SESSIONSTORAGE_HOSTNAME:$SESSIONSTORAGE_PORT"web:locations:'/':root:'web'passthru:'/index.php'services:# The name of the service container. Must be unique within a project.redissession:type:"redis-persistent:7.2"
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:source:root:"myapp"type:"php:8.4"# PHP extensions.runtime:extensions:- redis# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:redissession:service:redissessionendpoint:redisvariables:php:session.save_handler:redissession.save_path:"tcp://$SESSIONSTORAGE_HOSTNAME:$SESSIONSTORAGE_PORT"web:locations:'/':root:'web'passthru:'/index.php'services:# The name of the service container. Must be unique within a project.redissession:type:"redis-persistent:7.2"
# Application metrics [Continuous profiling for Go](https://docs.upsun.com/increase-observability/application-metrics/go.html)
Feature Availability
By default, Upsun offers 15 minutes of continuous profiling per project and for free.
To get 30 days of continuous profiling per project and for a fixed fee, upgrade to the Continuous Profiling add-on.
## Continuous profiling on Upsun
Upsun [Continuous Profiler](./cont-prof.md) is powered by [Blackfire](../../../increase-observability/application-metrics/blackfire.md).
It is available directly from the Console under the `Profiling` tab of your environments.
The GO continuous profiling is currently made across 6 dimensions:
- **Allocations**: Number of objects allocated
- **Allocated Memory**: Number of bytes allocated
- **CPU**: Time spent running on the CPU
- **Goroutines**: Number of goroutines (both on-CPU and off-CPU)
- **Heap Live Objects**: Number of objects allocated that are not yet garbage collected
- **Heap Live Size**: Number of bytes allocated that are not yet garbage collected
The default sampling frequency is 100 Hz. This means the Go continuous profiler is
collecting information 100 times per second.
## Prerequisites
Upsun Continuous Profiler requires [`Go >=1.18`](/languages/go.md).
## Installation
Get the [Blackfire Continuous Profiler Go library](https://github.com/blackfireio/go-continuous-profiling):
```bash
go get github.com/blackfireio/go-continuous-profiling
```
## Go continuous profiler API
The Go continuous profiler API has two functions:
```go
func Start(opts ...Option) error {}
func Stop() {}
```
### `func Start(opts ...Option) error`
`Start` starts the continuous profiler probe. It collects profiling information and uploads
it to the Blackfire Agent periodically.
```go
profiler.Start(
profiler.WithCPUDuration(3 * time.Second),
profiler.WithCPUProfileRate(1000),
profiler.WithProfileTypes(profiler.CPUProfile, profiler.HeapProfile, profiler.GoroutineProfile),
profiler.WithLabels({
"key1": "value1",
"key2": "value2",
}),
profiler.WithUploadTimeout(5 * time.Second),
)
defer profiler.Stop()
```
The `Start` function accepts the following options:
- `WithCPUDuration`: specifies the length at which to collect CPU profiles.
The default is 45 seconds. Can also be set via the environment variable `BLACKFIRE_CONPROF_CPU_DURATION`.
- `WithCPUProfileRate`: sets the CPU profiling rate in Hz (number of samples per second).
The default is defined by the Go runtime as 100 Hz. Can also be set via the environment
variable `BLACKFIRE_CONPROF_CPU_PROFILERATE`.
- `WithProfileTypes`: sets the profiler types. Multiple profile types can be set (`profiler.CPUProfile`, `profiler.HeapProfile`, `profiler.GoroutineProfile`).
The default is `Profiler.CPUProfile`.
- `WithLabels`: sets custom labels specific to the profile payload that is sent.
- `WithUploadTimeout`: sets the upload timeout of the message that is sent to the Blackfire Agent.
The default is 10 seconds. Can also be set via the environment variable `BLACKFIRE_CONPROF_UPLOAD_TIMEOUT`.
Note:
If the same parameter is set by both an environment variable and a Start call, the explicit
parameter in the Start call takes precedence.
There is also some additional configuration that can be done using environment variables:
- `BLACKFIRE_LOG_FILE`: Sets the log file. The default is logging to `stderr`.
- `BLACKFIRE_LOG_LEVEL`: Sets the log level. The default is logging only errors.
### `func Stop()`
Stops the continuous profiling probe.
## An example application
1. Get the Blackfire Continuous Profiler Go library
```bash
go get github.com/blackfireio/go-continuous-profiling
```
2. Save the following code as `main.go` and run as follows:
```bash
go run main.go
```
```go
package main
import (
"crypto/md5"
"encoding/hex"
"io"
"time"
profiler "github.com/blackfireio/go-continuous-profiling"
)
func doSomethingCpuIntensive() {
md5Hash := func(s string) string {
h := md5.New()
io.WriteString(h, s)
return hex.EncodeToString(h.Sum(nil))
}
for i := 0; i < 1_000_000; i++ {
md5Hash("UpsunIsCoolAndSoAreYou")
}
}
func main() {
err := profiler.Start(
profiler.WithAppName("my-app"),
)
if err != nil {
panic("Error while starting Profiler")
}
defer profiler.Stop()
for i := 0; i < 15; i++ {
doSomethingCpuIntensive()
time.Sleep(1 * time.Second)
}
}
```
# Application metrics [Continuous profiling for Node.js](https://docs.upsun.com/increase-observability/application-metrics/nodejs.html)
Feature Availability
By default, Upsun offers 15 minutes of continuous profiling per project and for free.
To get 30 days of continuous profiling per project and for a fixed fee, upgrade to the Continuous Profiling add-on.
## Continuous profiling on Upsun
Upsun Continuous Profiling is powered by [Blackfire](../../../increase-observability/application-metrics/blackfire.md).
It is available directly from the Console under the `Profiling` tab of your environments.
The Node.js continuous profiling is currently made across 3 dimensions:
- **CPU Time**: Time spent running on the CPU
- **Wall-time**: Elapsed time per function call
- **Heap**: Memory allocation and reserved space over time
The default sampling frequency is 100 Hz. This means the Node.js continuous profiler is
collecting information 100 times per second.
## Prerequisites
Upsun Continuous Profiler requires [`Node.js >= 16.0.0`](/languages/nodejs/_index.md).
## Installation
Get the [Blackfire Continuous Profiler NodeJS library](https://github.com/blackfireio/node-continuous-profiling/):
```shell
npm install @blackfireio/node-tracing
```
```js
const Blackfire = require('@blackfireio/node-tracing');
```
## NodeJS continuous profiler API
The NodeJS continuous profiler API has two functions:
```js
function start(config) {}
function stop() {}
```
### `function start(config) {}`
The `start` function starts the continuous profiler probe.
It collects profiling information in the background and periodically uploads it to the Blackfire Agent until the `stop` function is called.
```js
const Blackfire = require('@blackfireio/node-tracing');
Blackfire.start({
appName: 'my-app'
});
// your application...
// If needed, you can stop profiling before cpuDuration
// Blackfire.stop();
```
The `start` function accepts an object as a parameter with the following keys:
- `appName`: name of the application
- `durationMillis`: time in milliseconds for which to collect profile (default: 45_000)
- `cpuProfileRate`: average sampling frequency in Hz. (default: 100)
- `labels`: Labels to add to the profile. (default: {})
- `uploadTimeoutMillis`: Timeout in milliseconds for the upload request (default: 10000)
### `function stop() {}`
Stops the continuous profiling probe.
## An example application
1. Get the Continuous Profiler NodeJS library
```shell
npm install express @blackfireio/node-tracing
```
2. Create `index.js` with the following code
```js
const Blackfire = require('@blackfireio/node-tracing');
const express = require('express')
const crypto = require("crypto");
const app = express()
const port = 3000
app.get('/', (req, res) => {
const salt = crypto.randomBytes(128).toString("base64");
const hash = crypto.pbkdf2Sync("this is my password", salt, 10000, 512, "sha512");
res.send('Hello World!');
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
Blackfire.start({appName: 'blackfire-example'});
})
```
3. Run the Node.js server
```bash
node index.js# Application metrics [Continuous profiling for PHP](https://docs.upsun.com/increase-observability/application-metrics/php.html)
Feature Availability
By default, Upsun offers 15 minutes of continuous profiling per project and for free.
To get 30 days of continuous profiling per project and for a fixed fee, upgrade to the Continuous Profiling add-on.
Upsun [Continuous Profiler](./cont-prof.md) is powered by [Blackfire](../../../increase-observability/application-metrics/blackfire.md).
It is available directly the [Console](/administration/web/_index.md), under the **Profiling** tab of your environments.
The PHP continuous profiling is currently made across 4 dimensions:
- **CPU Time**: Time spent running on the CPU
- **Wall-time**: Elapsed time per function call
- **Allocated Memory**: Number of bytes allocated in memory
- **Allocations**: Time spent running on the CPU
The default sampling frequency is 100 Hz. This means the PHP continuous profiler is
collecting information 100 times per second.
## Prerequisites
Upsun Continuous Profiler requires [`PHP >=8.2`](/languages/php/_index.md).
## Installation
The Blackfire Continuous Profiler PHP library is included by default in all
PHP images matching its requirements. There is no installation required.
## Configuration
The PHP continuous profiler is enabled by default without configuration.
Optionally, you can override the following environment variables:
- `DD_PROFILING_ENABLED=true`: forces the PHP continuous profiler activation/deactivation
- `DD_PROFILING_LOG_LEVEL=off`: controls the PHP continuous profiler log level# Application metrics [Continuous profiling for Python](https://docs.upsun.com/increase-observability/application-metrics/python.html)
Feature Availability
By default, Upsun offers 15 minutes of continuous profiling per project and for free.
To get 30 days of continuous profiling per project and for a fixed fee, upgrade to the Continuous Profiling add-on.
Upsun [Continuous Profiler](./cont-prof.md) is powered by [Blackfire](../../../increase-observability/application-metrics/blackfire.md).
It is available directly from the [Console](/administration/web/_index.md), under the **Profiling** tab of your environments.
The PHP continuous profiling is currently made across 4 dimensions:
- **CPU Time**: Time spent running on the CPU
- **Wall-time**: Elapsed time per function call
- **Heap Live Size**: Number of bytes allocated that are not yet garbage collected
- **Allocated Memory**: Number of bytes allocated in memory
- **Allocations**: Time spent running on the CPU
The default sampling frequency is 100 Hz. This means the Python continuous profiler is
collecting information 100 times per second.
## Prerequisites
Upsun Continuous Profiler requires [`Python >=3.7.0`](/languages/python/_index.md).
## Installation
The [Blackfire Continuous Profiler Python library](https://github.com/blackfireio/python-continuous-profiling) is included by default in all
Python images matching its requirements. There is no installation required.
## Python continuous profiler API
The Python profiler API (`profiler`) can be initiated with the following options:
- `application_name`: the application name.
- `period`: specifies the length at which to collect CPU profiles. The default is 45 seconds.
- `upload_timeout`: observability data upload timeout. The default is 10 seconds.
- `labels`: a dict containing the custom labels specific to the profile payload that is sent.
The Python continuous profiler API has two functions:
``` python
def start():
def stop():
```
| Function | Description |
| ---------------------- | ----------- |
| `def start():` | The `start` function starts the continuous profiler probe. It collects profiling information in the background and periodically uploads it to the Blackfire Agent until the ``stop`` function is called. |
| `def stop():` |Stops the continuous profiling probe. |
## Example
Here is an example of how you can initiate the Python `profiler` on a basic app:
1. Create `example.py` with the following code:
``` python
def foo():
import time
time.sleep(1.0)
profiler = Profiler(application_name="my-python-app", labels={'my-extra-label': 'data'})
profiler.start()
foo()
profiler.stop()
```
2. Run the app:
``` bash
python example.py
```
# Application metrics [Continuous profiling for Ruby](https://docs.upsun.com/increase-observability/application-metrics/ruby.html)
Upsun [Continuous Profiler](./cont-prof.md) is powered by [Blackfire](../../../increase-observability/application-metrics/blackfire.md).
It is available directly the [Console](/administration/web/_index.md), under the **Profiling** tab of your environments.
The Ruby continuous profiling is currently made across 3 dimensions:
- **CPU Time**: Time spent running on the CPU
- **Wall-time**: elapsed time per function call
- **Allocations**: Time spent running on the CPU
The default sampling frequency is 100 Hz. This means the Ruby continuous profiler is
collecting information 100 times per second.
## Prerequisites
Upsun Continuous Profiler requires [`Ruby >= 2.5`](/languages/ruby.md).
## Installation
1. Add the `datadog` gem to your `Gemfile` or `gems.rb` file:
``` bash
gem 'datadog', '~> 2.0'
```
2. Install the gems running the `bundle install` command.
3. Add the ``ddprofrb exec`` command to your Ruby application start command:
``` bash
bundle exec ddprofrb exec ruby myrubyapp.rb
```
Rails example:
``` bash
bundle exec ddprofrb exec bin/rails s
```
Alternatively, start the profiler by adding the following code in your application's entry point if you can't start it using `ddprofrb exec`:
``` bash
require 'datadog/profiling/preload'
```
# Application metrics [Continuous profiling for Rust](https://docs.upsun.com/increase-observability/application-metrics/rust.html)
Upsun [Continuous Profiler](./cont-prof.md) is powered by [Blackfire](../../../increase-observability/application-metrics/blackfire.md).
It is available directly the [Console](/administration/web/_index.md), under the **Profiling** tab of your environments.
The Rust continuous profiling is currently made across 3 dimensions:
- **CPU Time**: Time spent running on the CPU
- **Allocated Memory**: Number of bytes allocated in memory
- **Allocations**: Time spent running on the CPU
The default sampling frequency is 100 Hz. This means the Rust continuous profiler is
collecting information 100 times per second. The allocated memory sampling frequency is 524288 Hz.
## Installation
The Blackfire Continuous Profiler Rust library is included by default in all
Rust images. There is no installation required nor minimal Rust version needed.
## Configuration
The Rust continuous profiler is enabled by default without configuration.
It is recommended to build your Rust application in [debug mode](https://doc.rust-lang.org/book/ch14-01-release-profiles.html) to benefit from comprehensive stacktrace and information that could be obfuscated and collapsed otherwise.
```shell
$ cargo build
```
# Set up multiple apps in a single project [Define relationships between your multiple apps](https://docs.upsun.com/create-apps/multi-app/relationships.html)
When you set up a project containing multiple applications,
by default your apps can't communicate with each other.
To enable connections, define relationships between apps using the `http` endpoint.
You can't define circular relationships.
If `app1` has a relationship to `app2`, then `app2` can't have a relationship to `app1`.
If you need data to go both ways, consider coordinating through a shared data store,
like a database or [RabbitMQ server](/add-services/rabbitmq.md).
Relationships between apps use HTTP, not HTTPS.
This is still secure because they're internal and not exposed to the outside world.
## Relationships example
You have two apps, `app1` and `app2`, and `app1` needs data from `app2`.
In your app configuration for `app1`, define a relationship to `app2`:
```yaml {configFile="app"}
applications:
app1:
relationships:
api:
service: "app2"
endpoint: "http"
```
Once they're both built, `app1` can access `app2` at the following URL: `http://api.internal`.
The specific URL is always available through the [service environment variables](/development/variables/_index.md#service-environment-variables),
or through the [`PLATFORM_RELATIONSHIPS` variable](/development/variables/use-variables.md#use-provided-variables):
# Add services [Solr (Search service)](https://docs.upsun.com/add-services/solr.html)
Apache Solr is a scalable and fault-tolerant search index.
Solr search with generic schemas provided, and a custom schema is also supported. See the [Solr documentation](https://lucene.apache.org/solr/6_3_0/index.html) for more information.
## Supported versions
You can select the major and minor version.
Patch versions are applied periodically for bug fixes and the like.
When you deploy your app, you always get the latest available patches.
9.6
9.4
9.2
9.1
8.11
### Deprecated versions
The following versions are [deprecated](/glossary.html#deprecated-versions).
They're available, but they aren't receiving security updates from upstream and aren't guaranteed to work.
They'll be removed in the future,
so migrate to one of the [supported versions](#supported-versions).
8.6
8.4
8.0
7.7
7.6
6.6
6.3
4.10
3.6
## Relationship reference
For each service [defined via a relationship](#usage-example) to your application,
Upsun automatically generates corresponding environment variables within your application container,
in the ``$_`` format.
Here is example information available through the [service environment variables](/development/variables/_index.md#service-environment-variables) themselves,
or through the [``PLATFORM_RELATIONSHIPS`` environment variable](/development/variables/use-variables.md#use-provided-variables).
You can obtain the complete list of available service environment variables in your app container by running upsun ssh env.
Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the service environment variables directly rather than hard coding any values.
For some advanced use cases, you can use the PLATFORM_RELATIONSHIPS environment variable.
The structure of the PLATFORM_RELATIONSHIPS environment variable can be obtained by running upsun relationships in your terminal:
# Decode the built-in credentials object variable.exportRELATIONSHIPS_JSON=$(echo$PLATFORM_RELATIONSHIPS| base64 --decode)# Set environment variables for individual credentials.exportAPP_SOLR_HOST="$(echo$RELATIONSHIPS_JSON| jq -r '.solr[0].host')"
## Usage example
### 1. Configure the service
To define the service, use the ``solr`` type:
```yaml {configFile="app"}
services:
# The name of the service container. Must be unique within a project.
:
type: solr:
```
Note that changing the name of the service replaces it with a brand new service and all existing data is lost. Back up your data before changing the service.
### 2. Define the relationship
To define the relationship, use the following configuration:
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<SERVICE_NAME>:
You can define <SERVICE_NAME> as you like, so long as it’s unique between all defined services
and matches in both the application and services configuration.
The example above leverages default endpoint configuration for relationships.
That is, it uses default endpoints behind-the-scenes, providing a relationship
(the network address a service is accessible from) that is identical to the name of that service.
With the above definition, the application container (<APP_NAME>) now has access to the service via the relationship <SERVICE_NAME> and its corresponding service environment variables.
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.<APP_NAME>:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:<RELATIONSHIP_NAME>:service:<SERVICE_NAME>endpoint:solr
You can define <SERVICE_NAME> and <RELATIONSHIP_NAME> as you like, so long as it’s unique between all defined services and relationships
and matches in both the application and services configuration.
The example above leverages explicit endpoint configuration for relationships.
applications:# The name of the app container. Must be unique within a project.myapp:# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:solr:services:# The name of the service container. Must be unique within a project.solr:type:solr:9.6
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:solr:service:solrendpoint:solrservices:# The name of the service container. Must be unique within a project.solr:type:solr:9.6
### Use in app
To use the configured service in your app, add a configuration file similar to the following to your project.
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"[...]# Relationships enable access from this app to a given service.# The example below shows simplified configuration leveraging a default service# (identified from the relationship name) and a default endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:solr:services:# The name of the service container. Must be unique within a project.solr:type:solr:9.6
.upsun/config.yaml
applications:# The name of the app container. Must be unique within a project.myapp:# The location of the application's code.source:root:"myapp"[...]# Relationships enable access from this app to a given service.# The example below shows configuration with an explicitly set service name and endpoint.# See the Application reference for all options for defining relationships and endpoints.relationships:solr:service:solrendpoint:solrservices:# The name of the service container. Must be unique within a project.solr:type:solr:9.6
This configuration defines a single application (`myapp`), whose source code exists in the `/myapp` directory.
`myapp` has access to the `solr` service, via a relationship whose name is [identical to the service name](#2-define-the-relationship)
(as per [default endpoint](/create-apps/app-reference/single-runtime-image#relationships) configuration for relationships).
From this, ``myapp`` can retrieve access credentials to the service through the [relationship environment variables](#relationship-reference).
```bash {location="myapp/.environment"}
# Set environment variables for individual credentials.
# For more information, please visit https://docs.upsun.com/development/variables.html#service-environment-variables.
export QUEUE_SCHEME=${SOLR_SCHEME}
export QUEUE_USERNAME=${SOLR_USERNAME}
export QUEUE_PASSWORD=${SOLR_PASSWORD}
export QUEUE_HOST=${SOLR_HOST}
export QUEUE_PORT=${SOLR_PORT}
# Set a single RabbitMQ connection string variable for AMQP.
export AMQP_URL="${QUEUE_SCHEME}://${QUEUE_USERNAME}:${QUEUE_PASSWORD}@${QUEUE_HOST}:${QUEUE_PORT}/"
```
The above file — ``.environment`` in the ``myapp`` directory — is automatically sourced by Upsun into the runtime environment, so that the variable ``SEARCH_URL`` can be used within the application to connect to the service.
Note that ``SEARCH_URL``, and all Upsun [service environment variables](/development/variables/_index.md#service-environment-variables) like ``SOLR_HOST``, are environment-dependent.
Unlike the build produced for a given commit,
they can’t be reused across environments and only allow your app to connect to a single service instance on a single environment.
A file very similar to this is generated automatically for your when using the ``upsun ify`` command to [migrate a codebase to Upsun](/get-started/_index.md).
## Solr 4
For Solr 4, Upsun supports only a single core per server called `collection1`.
You must provide your own Solr configuration via a `core_config` key in your `.upsun/config.yaml`:
```yaml {configFile="services"}
services:
# The name of the service container. Must be unique within a project.
solr:
type: "solr:4.10"
configuration:
core_config: !archive "DIRECTORY"
```
DIRECTORY points to a directory in the Git repository, in or below the `.upsun/` folder. This directory needs to contain everything that Solr needs to start a core. At the minimum, `solrconfig.xml` and `schema.xml`.
For example, place them in `.upsun/solr/conf/` such that the `schema.xml` file is located at `.upsun/solr/conf/schema.xml`. You can then reference that path like this -
```yaml {configFile="services"}
services:
# The name of the service container. Must be unique within a project.
solr:
type: "solr:4.10"
configuration:
core_config: !archive "solr/conf/"
```
## Solr 6 and later
For Solr 6 and later Upsun supports multiple cores via different endpoints. Cores and endpoints are defined separately, with endpoints referencing cores. Each core may have its own configuration or share a configuration. It is best illustrated with an example.
```yaml {configFile="services"}
services:
# The name of the service container. Must be unique within a project.
solr:
type: solr:9.6
configuration:
cores:
mainindex:
conf_dir: !archive "core1-conf"
extraindex:
conf_dir: !archive "core2-conf"
endpoints:
main:
core: mainindex
extra:
core: extraindex
```
The above definition defines a single Solr 9.6 server. That server has 2 cores defined:
- `mainindex` — the configuration for which is in the `.upsun/core1-conf` directory
- `extraindex` — the configuration for which is in the `.upsun/core2-conf` directory.
It then defines two endpoints: `main` is connected to the `mainindex` core while `extra` is connected to the `extraindex` core. Two endpoints may be connected to the same core but at this time there would be no reason to do so. Additional options may be defined in the future.
Each endpoint is then available in the relationships definition in `.upsun/config.yaml`. For example, to allow an application to talk to both of the cores defined above its configuration should contain the following:
```yaml {configFile="app"}
applications:
# The name of the app container. Must be unique within a project.
myapp:
type: "php:8.4"
source:
root: "myapp"
[...]
# Relationships enable access from this app to a given service.
# The example below shows configuration with explicitly set service names and endpoints.
# See the Application reference for all options for defining relationships and endpoints.
relationships:
solrsearch1:
service: solr
endpoint: main
solrsearch2:
service: solr
endpoint: extra
services:
# The name of the service container. Must be unique within a project.
solr:
type: solr:9.6
configuration:
cores:
mainindex:
conf_dir: !archive "core1-conf"
extraindex:
conf_dir: !archive "core2-conf"
endpoints:
main:
core: mainindex
extra:
core: extraindex
```
That is, the application's environment would include a `solrsearch1` relationship that connects to the `main` endpoint, which is the `mainindex` core, and a `solrsearch2` relationship that connects to the `extra` endpoint, which is the `extraindex` core.
The relationships array would then look something like the following:
```json
{
"solrsearch1": [
{
"path": "solr/mainindex",
"host": "248.0.65.197",
"scheme": "solr",
"port": 8080
}
],
"solrsearch2": [
{
"path": "solr/extraindex",
"host": "248.0.65.197",
"scheme": "solr",
"port": 8080
}
]
}
```
### Configsets
For even more customizability, it's also possible to define Solr configsets. For example, the following snippet would define one configset, which would be used by all cores. Specific details can then be overridden by individual cores using `core_properties`, which is equivalent to the Solr `core.properties` file.
```yaml {configFile="services"}
services:
# The name of the service container. Must be unique within a project.
solr:
type: solr:9.6
configuration:
configsets:
mainconfig: !archive "configsets/solr8"
cores:
english_index:
core_properties: |
configSet=mainconfig
schema=english/schema.xml
arabic_index:
core_properties: |
configSet=mainconfig
schema=arabic/schema.xml
endpoints:
english:
core: english_index
arabic:
core: arabic_index
```
In this example, `.upsun/configsets/solr8` contains the configuration definition for multiple cores. There are then two cores created:
- `english_index` uses the defined configset, but specifically the `.upsun/configsets/solr8/english/schema.xml` file
- `arabic_index` is identical except for using the `.upsun/configsets/solr8/arabic/schema.xml` file.
Each of those cores is then exposed as its own endpoint.
Note that not all core properties features make sense to specify in the `core_properties`. Some keys, such as `name` and `dataDir`, aren't supported, and may result in a `solrconfig` that fails to work as intended, or at all.
### Default configuration
#### Default for version 9+
If you don't specify any configuration, the following default is used:
```yaml {configFile="services"}
services:
# The name of the service container. Must be unique within a project.
solr:
type: solr:9.6
configuration:
cores:
collection1:
conf_dir: !archive "example"
endpoints:
solr:
core: collection1
```
The example configuration directory is equivalent to the [Solr example configuration set](https://github.com/apache/solr/tree/main/solr/server/solr/configsets/sample_techproducts_configs/conf).
This default configuration is designed only for testing.
You are strongly recommended to define your own configuration with a custom core and endpoint.
#### Default for versions below 9
If you don't specify any configuration, the following default is used:
```yaml {configFile="services"}
services:
# The name of the service container. Must be unique within a project.
solr:
type: solr:8.4
configuration:
cores:
collection1: {}
endpoints:
solr:
core: collection1
```
The default configuration is based on an older version of the Drupal 8 Search API Solr module that is no longer in use.
You are strongly recommended to define your own configuration with a custom core and endpoint.
### Limitations
The recommended maximum size for configuration directories (zipped) is 2MB. These need to be monitored to ensure they don't grow beyond that. If the zipped configuration directories grow beyond this, performance declines and deploys become longer. The directory archives are compressed and string encoded. You could use this bash pipeline
```bash
echo $(($(tar czf - . | base64 | wc -c )/(1024*1024))) Megabytes
```
inside the directory to get an idea of the archive size.
The configuration directory is a collection of configuration data, like a data dictionary, e.g. small collections of key/value sets. The best way to keep the size small is to restrict the directory context to plain configurations. Including binary data like plugin `.jar` files inflates the archive size, and isn't recommended.
## Accessing the Solr server administrative interface
Because Solr uses HTTP for both its API and admin interface it's possible to access the admin interface over an SSH tunnel.
```bash
upsun tunnel:single --relationship RELATIONSHIP_NAME
```
By default, this opens a tunnel at `127.0.0.1:30000`.
You can now open `http://localhost:30000/solr/` in a browser to access the Solr admin interface.
Note that you can't create indexes or users this way,
but you can browse the existing indexes and manipulate the stored data.
## Available plugins
This is the complete list of plugins that are available and loaded by default:
| Plugin | Description | 8.11 | 9.x |
|------------------------------------------------------------------------------------|--------------------------------------------------------|------|-----|
| [JTS](https://solr.apache.org/guide/8_1/spatial-search.html#jts-and-polygons-flat) | Library for creating and manipulating vector geometry. |* |* |
| [ICU4J](https://solr.apache.org/guide/8_3/language-analysis.html) | Library providing Unicode and globalization support. |* |* |
## Upgrading
The Solr data format sometimes changes between versions in incompatible ways. Solr doesn't include a data upgrade mechanism as it is expected that all indexes can be regenerated from stable data if needed. To upgrade (or downgrade) Solr you need to use a new service from scratch.
There are two ways of doing that.
### Destructive
In your `.upsun/config.yaml` file, change the version of your Solr service *and* its name.
Be sure to also update the reference to the now changed service name in it's corresponding application's `relationship` block.
When you push that to Upsun, the old service is deleted and a new one with the name is created, with no data. You can then have your application re-index data as appropriate.
This approach has the downside of temporarily having an empty Solr instance, which your application may or may not handle gracefully, and needing to rebuild your index afterward. Depending on the size of your data that could take a while.
### Transitional
For a transitional approach you temporarily have two Solr services. Add a second Solr service with the new version a new name and give it a new relationship in `.upsun/config.yaml`. You can optionally run in that configuration for a while to allow your application to populate indexes in the new service as well.
Once you're ready to cut over, remove the old Solr service and relationship. You may optionally have the new Solr service use the old relationship name if that's easier for your application to handle. Your application is now using the new Solr service.
This approach has the benefit of never being without a working Solr instance. On the downside, it requires two running Solr servers temporarily, each of which consumes resources and need adequate disk space. Depending on the size of your data that may be a lot of disk space.
# Getting started with Upsun [Set resources](https://docs.upsun.com/get-started/here/set-resources.html)
You can define how much CPU, memory, and disk you want to assign to each of your service and app containers.
If you don't explicitly set resources, Upsun uses [default resources](/manage-resources/resource-init.md) instead.
Upsun also offers several [resource initialization strategies](/manage-resources/resource-init.md) to help you allocate resources depending on your needs and use cases.
However, for the sake of this guide, let's set resources manually.
To do so, follow these steps:
1. Run the following command:
```bash {location="Terminal"}
upsun resources:set
```
This launches an interactive prompt to walk you through setting up your application's resources:
```bash {location="Terminal"}
upsun resources:set
Resource configuration for the project app (123456azerty), environment main (type: production):
+-----------------------+---------+---------+-------------+-----------+-----------+
| App or service | Size | CPU | Memory (MB) | Disk (MB) | Instances |
+-----------------------+---------+---------+-------------+-----------+-----------+
| myapp | 1 | 1 | 384 | N/A | 1 |
| []| 0.1 | 0.1 | 128 | N/A | 1 |
+-----------------------+---------+---------+-------------+-----------+-----------+
```
2. Select the profile size you want applied to your application image. For instance, `0.1`:
```bash {location="Terminal"}
App: myapp
Choose a profile size:
[0.1 ] CPU 0.1, memory 64 MB
[0.25] CPU 0.25, memory 128 MB
[0.5 ] CPU 0.5, memory 224 MB
[1 ] CPU 1, memory 384 MB
[2 ] CPU 2, memory 704 MB
[4 ] CPU 4, memory 1216 MB
[6 ] CPU 6, memory 1728 MB
[8 ] CPU 8, memory 2240 MB
[10 ] CPU 10, memory 2688 MB
> 0.1
```
3. Define how many [instances](/manage-resources/adjust-resources#horizontal-scaling) of your application container you want to deploy. For instance, `1`:
```bash {location="Terminal"}
Enter the number of instances (default: 1): 1
```
4. To confirm your choices, select `Y`.
Upsun grabs the previous built images from earlier, applies your resource selections to them, and deploys your full application!
Note
If the deployment fails, you may need to set the resources again.
# Add services [Varnish](https://docs.upsun.com/add-services/varnish.html)
Varnish is a popular HTTP proxy server, often used for caching.
You usually don't need it with Upsun as the standard router includes HTTP cache
and a CDN would cover more advanced uses.
But you can include Varnish as a service.
## Supported versions
You can select the major and minor version.
Patch versions are applied periodically for bug fixes and the like.
When you deploy your app, you always get the latest available patches.
7.3
7.2
6.0
## How it works
All incoming requests go through the [standard router](../define-routes/_index.md).
The Varnish service sits between the router and all apps in the project.
``` mermaid
graph LR
A(Request) -->B(Router)
B --> C{Varnish}
C -->D[App 1]
C -->E[App 2]
```
## Usage example
### 1. Configure the service
To define the service, use the `varnish` type:
```yaml {configFile="services"}
services:
# The name of the service container. Must be unique within a project.
:
type: varnish:
relationships:
: ':http'
configuration:
vcl: !include
type: string
path: config.vcl
```
Note that changing the name of the service replaces it with a brand new service and all existing data is lost.
Back up your data before changing the service.
The `relationships` block defines the connection between Varnish and your app.
You can define RELATIONSHIP_NAME as you like.
APP_NAME should match your app's `name` in the [app configuration](/create-apps/app-reference/single-runtime-image.md).
The `configuration` block must reference a VCL file inside the `.upsun` directory.
The `path` defines the file relative to the `.upsun` directory.
#### Example configuration
```yaml {configFile="services"}
applications:
# The name of the app container. Must be unique within a project.
myapp:
...
services:
# The name of the service container. Must be unique within a project.
varnish:
type: varnish:7.3
relationships:
application: 'myapp:http'
configuration:
vcl: !include
type: string
path: config.vcl
```
Notice the `relationship` (`application`) defined for the service `varnish` granting access to the application container `myapp`.
### 2. Create a VCL template
To tell Varnish how to handle traffic, in the `.upsun` directory
add a [Varnish Configuration Language (VCL) template](https://www.varnish-software.com/developers/tutorials/example-vcl-template/).
This template is supplemented by automatic additions from Upsun.
So you MUST NOT include certain features that you might elsewhere:
- A `vcl_init()` function:
The function is automatically generated based on the relationships you defined in Step 1.
Each defined relationship results in a backend with the same name.
- The VCL version at the start:
This is automatically generated.
- Imports for `std` or `directors`:
These are already imported.
You can import other [modules](#include-modules).
The file MUST include:
- A definition of which backend to use in a `vcl_recv()` subroutine.
The logic varies based on whether you have one or more apps.
Note
Misconfigured VCL files can result in incorrect and confusing behavior that’s hard to debug.
Upsun doesn’t help with VCL configuration options beyond the basic connection logic documented here.
You can see any compilation errors with the stats endpoint.
#### Example VCL template with one app
To serve one app, your VCL template needs at least the following function:
```bash {location="config.vcl" dir="true" }
sub vcl_recv {
set req.backend_hint = RELATIONSHIP_NAME.backend();
}
```
Where `RELATIONSHIP_NAME` is the name of the relationship you defined in [Step 1](#1-configure-the-service).
With the [example configuration](#example-configuration), that would be the following:
```bash {location="config.vcl" dir="true"}
sub vcl_recv {
set req.backend_hint = application.backend();
}
```
#### Example VCL template with multiple apps
If you have multiple apps fronted by the same Varnish instance,
your VCL templates needs logic to determine where each request is forwarded.
For example, you might have the following configuration for two apps:
```yaml {configFile="services"}
# The name of the service container. Must be unique within a project.
services:
varnish:
type: varnish:7.3
relationships:
blog:
service: blog
endpoint: http
main:
service: myapp
endpoint: http
configuration:
vcl: !include
type: string
path: config.vcl
applications:
# The name of the app container. Must be unique within a project.
blog:
# The location of the application's code.
source:
root: "backends/blog"
# The type of the application to build.
type: "php:8.4"
# The name of the app container. Must be unique within a project.
myapp:
# The location of the application's code.
source:
root: "backends/main"
# The type of the application to build.
type: "nodejs:8.4"
```
You could then define that all requests to `/blog/` go to the `blog` app and all other requests to the other app:
```bash {location="config.vcl" dir="true"}
sub vcl_recv {
if (req.url ~ "^/blog/") {
set req.backend_hint = blog.backend();
} else {
set req.backend_hint = main.backend();
}
}
```
### 3. Route incoming requests to Varnish
Edit your [route definitions](../define-routes/_index.md) to point to the Varnish service you just created.
Also disable the router cache as Varnish now provides caching.
To forward all incoming requests to Varnish rather than your app, you could have the following:
```yaml {configFile="routes"}
routes:
"https://{default}/":
type: upstream
upstream: "varnish:http"
cache:
enabled: false
```
Varnish forwards requests to your app based on the specified VCL template.
## Include modules
You can include the following optional modules in your VCL templates to add additional features:
- `cookie`
- `header`
- `saintmode`
- `softpurge`
- `tcp`
- `var`
- `vsthrottle`
- `xkey`
To use them, add an import to your template such as the following:
```bash {location="config.vcl" dir="true"}
import xkey;
```
## Circular relationships
At this time, Upsun doesn't support circular relationships between services and apps.
That means you can't add a relationship from an app fronted by Varnish to the Varnish service.
If you do so, then one of the relationships is skipped and the connection doesn't work.
## Rate limit connections
Sometimes you want to ensure that users, whether human or machine, can't overload your app with requests.
One tool to help is using Varnish to limit the rate at which connections can be made.
For example, say you want to make sure no one can make more than 20 requests within 10 seconds.
If they do, you want to block them from any more requests for 2 minutes.
To do so, [import the `vsthrottle` module](#include-modules)
and add logic similar to the following to your VCL template:
```bash {location="config.vcl" dir="true"}
import vsthrottle;
sub vcl_recv {
# The Upsun router provides the real client IP as X-Client-IP
# This replaces client.identity in other implementations
if (vsthrottle.is_denied(req.http.X-Client-IP, 20, 10s, 120s)) {
# Client has exceeded 20 requests in 10 seconds.
# When this happens, block that IP for the next 120 seconds.
return (synth(429, "Too Many Requests"));
}
# Set the standard backend for handling requests that aren't limited
set req.backend_hint = application.backend();
}
```
## Clear cache with a push
You may want at times to clear a specific part of your cache when you know the content is outdated.
With Varnish, you can clear the content with [purging and banning](https://varnish-cache.org/docs/trunk/users-guide/purging.html).
The following example shows how to set up purging.
1. Add an access control list to your VCL template:
```bash {location="config.vcl" dir="true"}
acl purge {
"localhost";
"192.0.2.0"/24;
}
```
This list ensures that only requests from the listed IPs are accepted.
Choose which IPs to allow.
If you are sending requests from an app, checkout the [outbound IPs for the region](../development/regions.md#public-ip-addresses).
Alternatively, you could code in a token that must be sent with the request.
2. Add purge handling:
```bash {location="config.vcl" dir="true"}
sub vcl_recv {
if (req.method == "PURGE") {
# The Upsun router provides the real client IP as X-Client-IP
# Use std.ip to convert the string to an IP for comparison
if (!std.ip(req.http.X-Client-IP, "0.0.0.0") ~ purge) {
# Deny all purge requests not from the allowed IPs
return(synth(403,"Not allowed."));
}
# Purge cache for allowed requests
return (purge);
}
...
}
```
Note
The snippet above has been produced for Varnish 7.x. If using a different version, consult the Varnish documentation for potential differences in syntax and required parameters.
3. Set up cache purging to suit your needs.
The following cURL call gives an example of how this can work:
```bash
curl -X PURGE "URL_TO_PURGE"
```
## Stats endpoint
The Varnish service also offers an `http+stats` endpoint,
which provides access to some Varnish analysis and debugging tools.
You can't use it from an app fronted by Varnish because of the restriction with [circular relationships](#circular-relationships).
To access the stats, create a **separate app** (`stats-app`) with a relationship *to* Varnish, but not *from* it.
Define [app configuration](/create-apps/app-reference/single-runtime-image.md) similar to the following:
```yaml {configFile="apps"}
applications:
# The name of the app container. Must be unique within a project.
stats-app:
# The location of the application's code.
source:
root: "stats"
# The type of the application to build.
type: "python:3.9"
# Unique relationship _to_ Varnish from 'stats-app', where no relationship
# is defined _from_ Varnish to the same app, to avoid circular relationships.
relationships:
varnishstats:
service: varnish
endpoint: http+stats
# The name of the app container. Must be unique within a project.
main-app:
# The location of the application's code.
source:
root: "backends/main"
# The type of the application to build.
type: "nodejs:22"
services:
# The name of the service container. Must be unique within a project.
varnish:
type: varnish:7.3
# Unique relationship _from_ Varnish _to_ 'main-app', where no relationship
# is defined _to_ Varnish to the same app, to avoid circular relationships.
relationships:
main:
service: "main-app"
endpoint: "http
configuration:
vcl: !include
type: string
path: config.vcl
```
You choose any valid name and type.
When the app is deployed, the app can access the Varnish service over HTTP to get diagnostic information.
The following paths are available:
- `/`: returns any error logged when generating the VCL template failed
- `/config`: returns the generated VCL template
- `/stats`: returns the output of `varnishstat`
- `/logs`: returns a streaming response of `varnishlog`
To access the Varnish stats endpoint from the command line:
1. Connect to your stats app [using SSH](../development/ssh/_index.md): `upsun ssh --app stats-app`
(replace `stats-app` with the name you gave the app).
2. Display the [relationships array](/create-apps/app-reference/single-runtime-image.md#relationships) with `echo $PLATFORM_RELATIONSHIPS | base64 -d | jq .`,
3. Query Varnish with `curl HOST:PORT/stats`, replacing `HOST` and `PATH` with the values from Step 2.
# Getting started with Upsun [Make changes to your project](https://docs.upsun.com/get-started/here/make-changes.html)
Upsun allows you to make changes to your project and test them on a preview environment before introducing them to Production.
In your project, the default branch (e.g. `main`, `master`, whichever chosen during project creation) always represents the production environment.
Other branches are for developing new features, fixing bugs, or updating the infrastructure.
To make changes to your project, follow these steps:
## 1. Create a new environment
Create a new environment (a Git branch) to make changes without impacting production:
Run the following command:
```bash {location="Terminal"}
upsun branch feat-a
```
This creates a new local `feat-a` Git branch based on the `main` Git branch
and activates a related environment on Upsun.
The new environment inherits the data (service data and assets) of its parent environment (the production environment here).
## 2. Make changes to your project
Depending on the stack you're using, change something within your source code.
## 3. Commit your changes
```bash {location="Terminal"}
git add index.js
git commit -m "Update source code"
```
## 4. Deploy your changes
Deploy your changes to the `feat-a` environment:
```bash {location="Terminal"}
upsun push
```
Note that each environment has its own domain name.
To open the URL of your new environment, run the following command:
```bash {location="Terminal"}
upsun environment:url --primary
```
Warnings
If your environment is inactive, you need to activate it first, using the following command:
Terminal
upsun environment:activate
## 5. Iterate
Iterate by changing the code, committing, and deploying.
When satisfied with your changes, merge them to the main branch,
and remove the feature branch:
```bash {location="Terminal"}
upsun merge
Are you sure you want to merge feat-a into its parent, main? [Y/n] y
upsun checkout main
git pull upsun main
upsun environment:delete feat-a
git fetch --prune
```
Note
Deploying after a merge is fast because the image built for the feature environment is reused for the targeted environment.
## 6. Keep your branch up to date
For a long running development branch, to keep the code up-to-date with the `main` branch, use `git merge main` or `git rebase main`.
You can also keep the data in sync with the parent environment by using [`upsun env:sync data`](/administration/cli/reference.html#environmentsynchronize).
# Add services [Vault key management service](https://docs.upsun.com/add-services/vault.html)
The Vault key management service (KMS) provides key management and access control for your secrets.
The Upsun Vault KMS offers the [transit secrets engine](https://developer.hashicorp.com/vault/docs/secrets/transit)
to sign, verify, encrypt, decrypt, and rewrap information.
Vault doesn't store the data sent to the transit secrets engine,
so it can be viewed as encryption as a service.
To store secrets such as API keys, create sensitive [environment variables](../development/variables/_index.md).
## Supported versions
You can select the major and minor version.
Patch versions are applied periodically for bug fixes and the like.
When you deploy your app, you always get the latest available patches.
1.12
## Relationship reference
For each service [defined via a relationship](#usage-example) to your application,
Upsun automatically generates corresponding environment variables within your application container,
in the ``$_`` format.
Here is example information available through the [service environment variables](/development/variables/_index.md#service-environment-variables) themselves,
or through the [``PLATFORM_RELATIONSHIPS`` environment variable](/development/variables/use-variables.md#use-provided-variables).
You can obtain the complete list of available service environment variables in your app container by running upsun ssh env.
Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the service environment variables directly rather than hard coding any values.
For some advanced use cases, you can use the PLATFORM_RELATIONSHIPS environment variable.
The structure of the PLATFORM_RELATIONSHIPS environment variable can be obtained by running upsun relationships in your terminal:
# Decode the built-in credentials object variable.exportRELATIONSHIPS_JSON=$(echo$PLATFORM_RELATIONSHIPS| base64 --decode)# Set environment variables for individual credentials.exportAPP_VAULT_HOST=="$(echo$RELATIONSHIPS_JSON| jq -r '.vault_secret[0].host')"
## Usage example
### 1. Configure the service
To define the service, use the `vault-kms` type:
```yaml {configFile="services"}
services:
# The name of the service container. Must be unique within a project.
:
type: vault-kms:
configuration:
endpoints:
:
- policy:
key:
type:
```
Note that changing the name of the service replaces it with a brand new service and all existing data is lost.
Back up your data before changing the service.
- SERVICE_NAME is the name you choose to identify the service.
- VERSION is a supported version of the service.
- ENDPOINT_ID is an identifier you choose for the endpoint.
- KEY_NAME is the name of the key to be stored in the Vault KMS.
- POLICY is one of the available [policies](#policies) based on what you want to accomplish.
- The `type` is one of:
- `sign`: for signing payloads, with the type `ecdsa-p256`
- `encrypt` (for encrypt`chacha20-poly1305`).
The `type` can't be changed after creation.
You can create multiple endpoints, such as to have key management separate from key use.
512 MB is the minimum required disk space for the Vault KMS service.
### 2. Define the relationship
To define the relationship, use the following configuration:
```yaml {configFile="app"}
applications:
# The name of the app container. Must be unique within a project.
:
# Relationships enable access from this app to a given service.
relationships:
:
service:
endpoint:
services:
# The name of the service container. Must be unique within a project.
:
type: vault-kms:
configuration:
endpoints:
:
- policy:
key:
type:
```
You can define `` as you like, so long as it's unique between all defined services
and matches in both the application and services configuration.
The example above leverages [default endpoint](/create-apps/app-reference/single-runtime-image#relationships) configuration for relationships.
That is, it uses default endpoints behind-the-scenes, providing a [relationship](/create-apps/app-reference/single-runtime-image#relationships)
(the network address a service is accessible from) that is identical to the _name_ of that service.
Depending on your needs, instead of default endpoint configuration,
you can use [explicit endpoint configuration](/create-apps/app-reference/single-runtime-image#relationships).
With the above definition, the application container (````) now has access to the service via the relationship ```` and its corresponding [service environment variables](/development/variables/_index.md#service-environment-variables).
If you split the service into multiple endpoints, define multiple relationships.
### Example configuration
```yaml {configFile="app"}
applications:
# The name of the app container. Must be unique within a project.
myapp:
relationships:
vault_secret: "vault-kms:manage_keys"
services:
# The name of the service container. Must be unique within a project.
vault-kms:
type: vault-kms:1.12
configuration:
endpoints:
manage_keys:
- policy: admin
key: vault-sign
type: sign
- policy: sign
key: vault-sign
type: sign
- policy: verify
key: vault-sign
type: sign
```
## Multiple endpoints example
```yaml {configFile="app"}
applications:
# The name of the app container. Must be unique within a project.
myapp:
relationships:
vault_manage:
service: vault-kms
endpoint: management
vault_sign:
service: vault-kms
endpoint: sign_and_verify
services:
# The name of the service container. Must be unique within a project.
vault-kms:
type: vault-kms:1.12
configuration:
endpoints:
management:
- policy: admin
key: admin-key
type: sign
sign_and_verify:
- policy: sign
key: signing-key
type: sign
- policy: verify
key: signing-key
type: sign
```
## Use Vault KMS
To connect your app to the Vault KMS, use a token that's defined in the [service environment variables](#relationship-reference).
With this token for authentication,
you can use any of the policies you [defined in your `.upsun/config.yaml` file](#1-configure-the-service).
You can obtain the complete list of available service environment variables in your app container by running ``upsun ssh env``.
Note that the information about the relationship can change when an app is redeployed or restarted or the relationship is changed. So your apps should only rely on the [service environment variables](/development/variables/_index.md#service-environment-variables) directly rather than hard coding any values.
The following examples use cURL as an example, which you could do in a hook or after accessing your app with SSH.
Adapt the examples for your app's language.
### Get the token
To make any calls to the Vault KMS, you need your token. Get it from the [service environment variables](#relationship-reference):
```bash
echo ${RELATIONSHIP_NAME_PASSWORD}"
```
`RELATIONSHIP_NAME` is the relationship name you [defined in your `.upsun/config.yaml` file](#2-define-the-relationship).
You can also store this as a variable:
```bash
VAULT_TOKEN=${RELATIONSHIP_NAME_PASSWORD}
```
A given token is valid for one year from its creation.
### Get the right URL
The [service environment variable](#relationship-reference) also contains the information you need to construct a URL for contacting the Vault KMS: the `host` and `port`.
Assign it to a variable as follows:
```bash
VAULT_URL=${RELATIONSHIP_NAME_HOST}:${RELATIONSHIP_NAME_PORT}
```
`RELATIONSHIP_NAME` is the name you [defined in your `.upsun/config.yaml` file](#2-define-the-relationship).
### Manage your keys
Your key names are [defined in your `.upsun/config.yaml` file](#1-configure-the-service). You can manage them if you've set an [admin policy](#policies) for them.
To get information on a key, such as its expiration date, run the following command:
```bash
curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
http://"$VAULT_URL"/v1/transit/keys/"$KEY_NAME" | jq .
```
`$KEY_NAME` is the name in your `.upsun/config.yaml` file.
To rotate the version of your key, run the following command:
```bash
curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
http://"$VAULT_URL"/v1/transit/keys/"$KEY_NAME">/rotate \
--request POST
```
### Sign and verify payloads
If you've set [sign and verify policies](#policies), you can use your keys to sign and verify various payloads, such as a JSON Web Token (JWT) for authentication in your app. Note that all payloads (all plaintext data) must be base64-encoded.
To sign a specific payload, run the following command:
```bash
curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
http://$VAULT_URL/v1/transit/sign/"$KEY_NAME"/sha2-512 \
--data "{\"input\": \"$(echo SECRET | base64)\"}"
```
The string at the end of the URL denotes the specific [hash algorithm used by the Vault KMS](https://www.vaultproject.io/api-docs/secret/transit#hash_algorithm).
You get back a JSON object that includes the signature for the payload:
```json
{
"request_id": "a58b549f-1356-4028-d191-4c9cd585ca25",
...
"data": {
"key_version": 1,
"signature": "vault-kms:v1:MEUCIAiN4UtXh..."
},
...
}
```
You can then use `data.signature` to sign things such as a JWT.
To verify a payload, run the following command:
```bash
curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
http://"$VAULT_URL"/v1/transit/verify/"$KEY_NAME"/sha2-512 \
--data "
{
\"input\": \"$(echo SECRET | base64)\",
\"signature\": \"$SIGNATURE\"
}"
```
You get back a JSON object that includes whether or not the signature is valid:
```json
{
"request_id": "5b624718-fd9d-37f6-8b95-b387379d2648",
...
"data": {
"valid": true
},
...
}
```
A `true` value means the signature matches and a `false` value means it doesn't.
### Encrypt and decrypt data
If you've set [encrypt and decrypt policies](#policies), you can use your keys to encrypt and decrypt any data you want. Note that all of plaintext data you work with must be base64-encoded.
To sign a specific payload, run the following command:
```bash
curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
http://$VAULT_URL/v1/transit/encrypt/"$KEY_NAME" \
--data "{\"plaintext\": \"$(echo SECRET | base64)\"}"
```
You get back a JSON object that includes your encrypted data:
```json
{
"request_id": "690d634a-a4fb-bdd6-9947-e895578b79d5",
...
"data": {
"ciphertext": "vault-kms:v1:LEtOWSwh3N...",
"key_version": 1
},
...
}
```
To decrypt data that you've already encrypted, run the following command:
```bash
curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
http://"$VAULT_URL"/v1/transit/decrypt/"$KEY_NAME" \
--data "
{
\"ciphertext\": \"$CIPHERTEXT\"
}"
```
You get back a JSON object that your decrypted data base64-encoded:
```json
{
"request_id": "bbd411ca-6ed7-aa8b-8177-0f35055ce613",
...
"data": {
"plaintext": "U0VDUkVUCg=="
},
...
}
```
To get the value un-encoded, add `| jq -r ".data.plaintext" | base64 -d` to the end of the `curl` command.
#### Rewrap encrypted data
If you have already encrypted data and you have [changed your key version](#manage-your-keys), you can rewrap the encrypted data with the new key.
Assuming `$CIPHERTEXT` stores your encrypted data (`vault:v1:LEtOWSwh3N...`), run the following command:
```bash
curl \
--header "X-Vault-Token: $VAULT_TOKEN" \
http://"$VAULT_URL"/v1/transit/rewrap/"$KEY_NAME" \
--data "
{
\"ciphertext\": \"$CIPHERTEXT\"
}"
```
In the JSON object that's returned, you can notice that the `ciphertext` is different (and now includes the new key version as a prefix) as is the `key_version`:
```json
{
...
"data": {
"ciphertext": "vault-kms:v2:ICRi0yAlH...",
"key_version": 2
},
...
}
```
## Policies
| Policy | Endpoint | Capabilities | Purpose |
| --------- | -------- | ------------ | ------- |
| `admin` | `transit/keys/${KEY}` | `read` | Access to key properties and various functions performed on keys such as rotation and deletion |
| | `transit/keys/${KEY}/*` | `read`, `create`, `update`, `delete` | |
| `sign` | `transit/sign/${KEY}/${HASH_ALGORITHM}` | `read`, `update` | Signing payloads with an existing key |
| `verify` | `transit/verify/${KEY}/${HASH_ALGORITHM}` | `read`, `update` | Verifying already signed payloads |
| `encrypt` | `transit/encrypt/${KEY}` | `read`, `update` | Encrypting data with an existing key |
| `decrypt` | `transit/decrypt/${KEY}` | `read`, `update` | Decrypting data with an existing key |
| `rewrap` | `transit/rewrap/${KEY}` | `read`, `update` | Re-encrypting data with a new key version without revealing the secret |
# Getting started with Upsun [Third party integrations](https://docs.upsun.com/get-started/here/third-party.html)
In this guide, you've configured and deployed a local copy of your codebase to Upsun.
You can continue to work, but the primary remote your team would share would be Upsun itself.
It's more likely that your codebase is on a third party Git service like GitHub, GitLab, or Bitbucket.
Now that you've learned the basics of Upsun configuration and deployment, you can create new projects within the management console, by choosing the **Connect repository** option to set up a GitHub application.
At this stage, if you want to make another remote (i.e. `origin`) the primary remote, and Upsun a deployment mirror, you can override your current configuration by setting up an integration:
- [BitBucket](/integrations/source/bitbucket.md)
- [GitHub](/integrations/source/github.md)
- [GitLab](/integrations/source/gitlab.md)
Once the integration is added, all commits on the service are mirrored, built, and deployed on Upsun.
# Getting started with Upsun [Get support](https://docs.upsun.com/get-started/here/support.html)
There are virtually no restrictions to you deploying any kind of application on Upsun, and we're excited to hear about your experiments!
Follow the links below to share your work, ask the community for help, and peek in on what others are working on.
Welcome to the Upsun community!
# Deploy Laravel on Upsun [FAQ](https://docs.upsun.com/get-started/stacks/laravel/faq.html)
## How can I access my application logs?
To display the application log file (`/var/log/app.log` file), run the following command:
```bash
upsun log app --tail
```
All the log messages generated by your app are sent to this `/var/log/app.log` file.
This includes language errors such as PHP errors, warnings, notices,
as well as uncaught exceptions.
The file also contains your application logs if you log on `stderr`.
This log doesn't include the default `laravel.log` located in `/storage`.
Note
Upsun manages the app.log file for you.
This is to prevent disks from getting filled and using very fast local drives instead of slower network disks.
Make sure your apps always output their logs to stderr.
With Laravel, you can change your logging configuration to use `memory` and stream `php://stderr`.
In your `config/logging.php` file, add or update the following configuration:
```php {location="config/logging.php"}
'memory' => [
'driver' => 'monolog',
'handler' => Monolog\Handler\StreamHandler::class,
'with' => [
'stream' => 'php://stderr',
],
'processors' => [
// Simple syntax...
Monolog\Processor\MemoryUsageProcessor::class,
// With options...
[
'processor' => Monolog\Processor\PsrLogMessageProcessor::class,
'with' => ['removeUsedContextFields' => true],
],
],
],
```
Warning
If you log deprecations, make sure you also log them on stderr.
## What's this "`Oops! An Error Occurred`" message about?
The `Oops! An Error Occurred` message comes from your app and is automatically generated based on the Laravel error template.
### The server returned a "`500 Internal Server Error`"
If your app's working as expected locally but you see the previous error message on Upsun,
it usually means you have a configuration error or a missing dependency.
To fix this issue, search your application logs.
They likely contain an error message describing the root cause:
```bash
upsun logs all
[app] [14-Aug-2020 10:52:27 UTC] [critical] Uncaught PHP Exception Exception: [...]
[app]
[php.access] 2020-08-14T10:52:27Z GET 500 2.386 ms 2048 kB 419.11% /
[access] 78.247.136.119 - - [14/Aug/2020:10:52:27 +0000] "GET / HTTP/1.1" 500 843 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36"
```
If the error occurs on a preview environment,
or on the main environment of a non-production project,
you can also enable Laravel's dev/debug mode to inspect the cause of the error
via the `APP_DEBUG` [environment variable](./environment-variables.md) in your
`.environment` file or via [upsun console](/development/variables):
```bash
# Enable debug mode
export APP_DEBUG=1
# Disable debug mode
export APP_DEBUG=0
```
## Other issues
For other issues unrelated to Laravel, see [Troubleshoot development](/development/troubleshoot.html).
# Deploy Symfony on Upsun [FAQ](https://docs.upsun.com/get-started/stacks/symfony/faq.html)
## Why is `DATABASE_URL` not defined during the build hook?
During the build hook, services are not available to avoid breaking the
application that is still live. That is why the Symfony integration does not
expose environment variables during the build hook.
The `cache:clear` command does not need to connect to the database by default,
except if you are using the Doctrine ORM and the database engine version is not
set in your configuration.
The version information can be set in your `.env` file or in the
`doctrine.yaml` configuration file. The only important pieces of information there are
the database engine and the version; everything else will be ignored.
Note that the environment variables are available in the deploy hook.
## How can I access my application logs?
To display the application log file (`/var/log/app.log` file), run the following command:
```bash
symfony log app --tail
```
All the log messages generated by your app are sent to this `/var/log/app.log` file.
This includes language errors such as PHP errors, warnings, notices,
as well as uncaught exceptions.
The file also contains your application logs if you log on `stderr`.
Note that Upsun manages the `/var/log/app.log` file for you.
This is to prevent disks from getting filled and using very fast local drives instead of slower network disks.
Make sure your apps always output their logs to `stderr`.
If you use Monolog, add the following configuration to your `config/packages/prod/monolog.yaml` file:
```gitignore
--- a/config/packages/prod/monolog.yaml
+++ b/config/packages/prod/monolog.yaml
@@ -11,7 +11,7 @@ monolog:
members: [nested, buffer]
nested:
type: stream
- path: "%kernel.logs_dir%/%kernel.environment%.log"
+ path: php://stderr
level: debug
buffer:
type: buffer
```
Warning
If you log deprecations, make sure you also log them on stderr.
## What's this "Oops! An Error Occurred" message about?
The *Oops! An Error Occurred* message comes from your app and is automatically generated based on the Symfony error template.
### The server returned a "500 Internal Server Error"

If your app's working as expected locally but you see the previous error message on Upsun,
it usually means you have a configuration error or a missing dependency.
To fix this issue, search your application logs.
They likely contain an error message describing the root cause:
```bash
symfony logs all
[app] [14-Aug-2020 10:52:27 UTC] [critical] Uncaught PHP Exception Exception: [...]
[app]
[php.access] 2020-08-14T10:52:27Z GET 500 2.386 ms 2048 kB 419.11% /
[access] 78.247.136.119 - - [14/Aug/2020:10:52:27 +0000] "GET / HTTP/1.1" 500 843 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36"
```
If the error occurs on a preview environment,
or on the main environment of a non-production project,
you can also enable Symfony's dev/debug mode to inspect the cause of the error:
```bash
# Enable debug mode
symfony env:debug
# Disable debug mode
symfony env:debug --off
```
### The server returned a "404 Not Found"
By default, new Symfony apps come without controllers, which means there's no homepage to show.
As a result, when you run your project locally, the following welcome page is displayed:

But when you run your project on Upsun, the following error is displayed instead:

This is because Upsun runs in production mode, leading Symfony to show a generic 404 error.
To fix this issue, [create your first Symfony page](https://symfony.com/doc/current/page_creation.html).
If you've already created a custom homepage, make sure you perform the following actions:
1. Commit all your files.
2. Run the `symfony deploy` command and check that the deployment is successful.
## Other issues
For other issues unrelated to Symfony, see [Troubleshoot development](/development/troubleshoot.html).
# Deploy Symfony on Upsun [Symfony CLI Tips](https://docs.upsun.com/get-started/stacks/symfony/symfony-cli-tips.html)
The [Symfony CLI](https://symfony.com/download) allows you to interact with your project from the command line.
It wraps the [Upsun CLI](/administration/cli/_index.md) with added features related to Symfony.
So when using Symfony, you can replace `upsun ` by `symfony upsun:` in all of your commands.
## Useful Symfony CLI commands
- Open the web administration console:
```bash
symfony upsun:web
```
- Open the URL of the current environment:
```bash
symfony upsun:url
```
- Open an SSH connection to your environment:
```bash
symfony upsun:ssh
```
- Configure a project for Upsun:
```bash
symfony project:init --upsun
```
- Get a list of all the domains:
```bash
symfony upsun:domains
```
- Create a new environment:
```bash
symfony upsun:branch new-branch
```
- Get a list of all the environments:
```bash
symfony upsun:environments
```
- Push code to the current environment:
```bash
symfony upsun:push
```
- Get a list of all the active projects:
```bash
symfony upsun:projects
```
- Add a user to the project:
```bash
symfony upsun:user:add
```
- List variables:
```bash
symfony upsun:variables
```
### Useful commands when using Symfony with a database
- Create a local dump of the remote database:
```bash
symfony upsun:db:dump --relationship database
```
- Run an SQL query on the remote database:
```bash
symfony upsun:sql 'SHOW TABLES'
```
- Import a local SQL file into a remote database:
```bash
symfony upsun:sql < my_database_backup.sql
```
| **Language** | **`runtime`** | **Supported `version`** |
|----------------------------------|---------------|-------------------------|
| [C#/.Net Core](/languages/dotnet.html) | `dotnet` | 7.0, 6.0, 8.0 |
| [Elixir](/languages/elixir.html) | `elixir` | 1.15, 1.14 |
| [Go](/languages/go.html) | `golang` | 1.23, 1.22, 1.21, 1.20 |
| [Java](/languages/java.html) | `java` | 21, 19, 18, 17, 11, 8 |
| [Lisp](/languages/lisp.html) | `lisp` | 2.1, 2.0, 1.5 |
| [JavaScript/Node.js](/languages/nodejs.html) | `nodejs` | 22, 20, 18, 16 |
| [PHP](/languages/php.html) | `php` | 8.4, 8.3, 8.2, 8.1 |
| [Python](/languages/python.html) | `python` | 3.12, 3.11, 3.10, 3.9, 3.8 |
| [Ruby](/languages/ruby.html) | `ruby` | 3.3, 3.2, 3.1, 3.0 |
| [Rust](/languages/rust.html) | `rust` | 1 || **Service** | **`type`** | **Supported `version`** |
|----------------------------------|---------------|-------------------------|
| [Headless Chrome](/add-services/headless-chrome.html) | `chrome-headless` | 120, 113, 95, 91, 86, 84, 83, 81, 80, 73 |
| [Elasticsearch](/add-services/elasticsearch.html) | `elasticsearch` | 8.5, 7.17 |
| [InfluxDB](/add-services/influxdb.html) | `influxdb` | 2.7, 2.3 |
| [Kafka](/add-services/kafka.html) | `kafka` | 3.7, 3.6, 3.4, 3.2 |
| [MariaDB/MySQL](/add-services/mysql.html) | `mariadb` | 11.4, 11.2, 11.0, 10.11, 10.6, 10.5, 10.4 |
| [Memcached](/add-services/memcached.html) | `memcached` | 1.6, 1.5, 1.4 |
| [MongoDB](/add-services/mongodb.html) | `mongodb` | |
| [MongoDB](/add-services/mongodb.html) | `mongodb-enterprise` | 7.0, 6.0, 5.0, 4.4 |
| [Network Storage](/add-services/network-storage.html) | `network-storage` | 2.0 |
| [OpenSearch](/add-services/opensearch.html) | `opensearch` | 2, 1 |
| [Oracle MySQL](/add-services/mysql.html) | `oracle-mysql` | 8.0, 5.7 |
| [PostgreSQL](/add-services/postgresql.html) | `postgresql` | 16, 15, 14, 13, 12 |
| [RabbitMQ](/add-services/rabbitmq.html) | `rabbitmq` | 3.13, 3.12 |
| [Redis](/add-services/redis.html) | `redis` | 7.2, 7.0, 6.2 |
| [Solr](/add-services/solr.html) | `solr` | 9.6, 9.4, 9.2, 9.1, 8.11 |
| [Varnish](/add-services/varnish.html) | `varnish` | 7.3, 7.2, 6.0 |
| [Vault KMS](/add-services/vault.html) | `vault-kms` | 1.12 |# Security and compliance [{{% vendor/name %}} WAF](https://docs.upsun.com/security/waf.html)
The Upsun WAF monitors requests to your app and blocks suspicious ones.
All traffic to Upsun endpoints is also filtered
using a system that takes into account traffic patterns and abuse scores.
## CRLF injection prevention
Carriage return and line feed (CRLF) injection occurs when an attacker injects a CRLF character sequence to manipulate HTTP requests.
CRLF injection can lead to [request smuggling](#request-smuggling),
[header injection](#header-injection), and [response splitting](#response-splitting) attacks.
To protect your app from such attacks, the WAF detects and blocks requests containing CRLF character sequences.
### Request smuggling
When a frontend server forwards HTTP requests to a backend server,
it usually sends a series of requests at once.
The backend server then parses the request headers
to determine where one request ends and the next one begins.
The [HTTP protocol](https://tools.ietf.org/html/rfc2616) provides two different headers
to specify where an HTTP request ends: `Content-Length` and `Transfer-Encoding`.
When the frontend and backend servers don’t agree on which header they should interpret as the end of a request,
attackers can smuggle requests. If a malicious request is injected, the backend server may misinterpret the boundaries
of the individual requests within the concatenated request, thereby processing a request differently from what was
intended. This can lead to various security risks such as data leakage, privilege escalation, and even remote code
execution.
The WAF detects and blocks requests that contain [both the `Content-Length` and `Transfer-Encoding` headers](#content-length-and-transfer-encoding-headers-together).
It also detects and blocks requests that include **both** of the following features of an attempt to inject a malicious request:
- A [CRLF character](#crlf-injection-prevention) or `http/\d`
- An `HTTP` or `WEBDAV` method name
### Header injection
During a header injection attack, the attacker tricks your app
into inserting extra HTTP headers into legitimate HTTP responses.
These attacks can happen when HTTP response headers are generated based on user input.
Header injection attacks can have various impacts,
including cookie injection, [cross-origin resource sharing](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) header injection,
and bypassing your content security policy.
Such attacks enable [response splitting](#response-splitting),
which in turn can lead to [cross-site scripting](https://developer.mozilla.org/en-US/docs/Glossary/Cross-site_scripting),
web cache poisoning, and so on.
The WAF detects header injection attempts occurring through the payload and the header itself.
By [blocking requests containing CRLF](#crlf-injection-prevention) character sequences,
the WAF prevents malicious data from being returned in a response header and interpreted by the client.
### Response splitting
When a user makes an HTTP request, the web server usually returns a single HTTP response.
But when an attacker succeeds in [injecting headers](#header-injection),
they can launch a [response splitting attack](https://www.cs.montana.edu/courses/csci476/topics/http_response_splitting.pdf).
During a response splitting attack, the attacker uses CRLF characters to inject additional HTTP responses into legitimate user requests.
This enables further attacks such as [cross-site scripting](https://developer.mozilla.org/en-US/docs/Glossary/Cross-site_scripting),
web cache poisoning, browser cache poisoning, and cross-user attacks.
As the WAF [blocks requests containing CRLF](#crlf-injection-prevention) character sequences,
your app is protected from response splitting attacks.
## HTTP protocol enforcement
In addition to protecting your site against [CRLF injection-related](#crlf-injection-prevention) attacks,
the WAF implements additional rules to enforce the HTTP protocol.
### Uniform Resource Identifier (URI) syntax
[RFC 3986](https://www.rfc-editor.org/rfc/rfc3986) defines the generic syntax for URIs.
When the WAF detects a URI with incorrect syntax, the incoming connection is terminated.
The request is then reconstructed on the internal Upsun network,
enforcing the valid format in transit.
### File upload limit
The WAF enforces a file upload limit.
By default, this limit is set at 250 MB.
You can customize the file upload limit by amending your [app configuration](/create-apps/_index.md).
In the [`web.locations` dictionary](/create-apps/app-reference/single-runtime-image.md#locations),
add your desired value for the `max_request_size` property.
### File extension restriction
The WAF enforces any file extension restriction you may have defined in your [app configuration](../../create-apps/_index.md).
To set up a file extension restriction,
adjust the [`web.locations` dictionary](/create-apps/app-reference/single-runtime-image.md#locations).
Set up [rules](/create-apps/app-reference/single-runtime-image.md#rules) to allow only certain file extensions on a given path.
### Disallowed requests and headers
#### `GET` requests with a body
The [HTTP specification](https://tools.ietf.org/html/rfc2616) allows for `GET` requests to have a body.
This enables attackers to try and force a request body on unsuspecting applications,
which could result in a [request smuggling attack](#request-smuggling).
To prevent such attacks, when the WAF detects a `GET` request,
it scans the request for a potential `Content-Length` or `Transfer-Encoding` header.
If one of those headers is found and the payload isn't `0` or empty,
all body-related headers are removed from the request.
The request is then passed through otherwise unaltered.
#### `Content-Length` and `Transfer-Encoding` headers together
According to the [HTTP specification](https://tools.ietf.org/html/rfc2616),
requests mustn't contain [both a `Content-Length` and a `Transfer-Encoding` header](https://tools.ietf.org/html/rfc7230#section-3.3.2).
This rule helps protect apps from [request smuggling](#request-smuggling).
The WAF detects and blocks requests featuring both headers
and forces requests to use [chunked transfer encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding)
only on the internal Upsun network.
#### Missing or empty `host` headers
As [routes are mapped](../../define-routes/_index.md) based on host names,
the Upsun WAF blocks requests with an empty or absent `host` header.
#### Other restricted HTTP headers
The following headers are disallowed: `Connection`, `Proxy-Authorization`, `TE`, and `Upgrade`.
## Slowloris DDoS attack prevention
Slowloris DDoS attacks use partial HTTP requests to open connections between a single computer and a targeted web server.
These connections are then kept open for as long as possible to overwhelm the web server.
While Apache web servers are vulnerable to Slowloris attacks, Nginx servers aren't.
Since Upsun router services use Nginx processes,
your projects are protected against such attacks.
# Connect securely with SSH [Authenticate with SSH keys](https://docs.upsun.com/development/ssh/ssh-keys.html)
To connect to your app using SSH keys, you need two keys:
* A **private key** you must keep _secret_
* A **public key** stored in your Upsun account
A given SSH key pair can only be linked to a single user account.
A key pair is valid for as long as you have access to the private key on the system from which you are connecting.
If you have a key pair available, you aren't prompted to login.
To keep connection secure, you need to regularly update the keys you use.
A well-encrypted key is no substitute for regular key rotation.
If you used GitHub to sign up for your Upsun account
your public keys from GitHub are automatically synced to your Upsun account.
So you can use them already with the CLI or to [connect to your app](./_index.md#2-connect-to-an-app-with-ssh).
## Add SSH keys
If you don't have keys already added,
you might be able to [find existing keys](#1a-find-your-keys) or else you need to [generate new keys](#1b-generate-new-keys).
### 1A. Find your keys
If you haven't used SSH keys before or it's been a while since you created the key,
skip right to [generating new keys](#1b-generate-new-keys).
If you have generated SSH keys before and want to find them on your system,
follow these instructions.
A public key file has a name ending in `.pub`.
It contains seemingly random lines of characters,
like this example of a public [RSA key](https://en.wikipedia.org/wiki/RSA_%28cryptosystem%29)
(note the email address at the end, which wouldn't be present in a private key):
```text
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC2nDRLgPANWParTiaGIgySG+thTtnqFGI1tMWyqDdfvH+5hL91w2tK9PzaP+NJ5hA/cOyh30YRFb52Y64toU16Ko5K1mLqNFJajjWEI5Y4VukG6betrWfqdQ7XBr/s7nBuDOFQ5+eKbvug4rRSCSo8CsEI1eI0VNQkC9HJWYK28k7KurMdTN7X/Z/4vknM4/Rm2bnMk2idoORQgomeZS1p3GkG8dQs/c0j/b4H7azxnqdcCaR4ahbytX3d49BN0WwE84C+ItsnkCt1g5tVADPrab+Ywsm/FTnGY3cJKKdOAHt7Ls5lfpyyug2hNAFeiZF0MoCekjDZ2GH2xdFc7AX/ your_email_address@example.com
```
To find your public key file:
1. Open a terminal.
2. Run the following commands:
```bash
cd ~/.ssh
ls -a
```
If you find a file ending in `.pub`,
copy the location and [add it to your Upsun account](#2-add-an-ssh-key-to-your-account).
If you don't find an existing key, [generate new keys](#1b-generate-new-keys).
### 1B. Generate new keys
If you're logged in using the [Upsun CLI](./_index.md#1-authenticate-with-the-cli),
generate a key and have it added to your Upsun account automatically.
1. In a terminal, run `upsun ssh-key:add`.
1. If necessary, log in to a browser.
1. Press `Y` and `enter` to create a new SSH key.
1. Copy the location of the generated key.
1. Run the following commands (replacing `PATH_TO_YOUR_KEY` with the location you copied):
```bash
eval $(ssh-agent)
ssh-add 'PATH_TO_YOUR_KEY'
```
To generate a key otherwise, GitHub has a good [walk-through for creating SSH key pairs](https://docs.github.com/en/authentication/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent) on various operating systems.
Then you need to [add it to your Upsun account](#2-add-an-ssh-key-to-your-account).
### 2. Add an SSH key to your account
Once you have the location of your public key, add it to your Upsun account.
If you're logged in using the [Upsun CLI](./_index.md#1-authenticate-with-the-cli),
in a terminal run the following command (replacing `PATH_TO_YOUR_KEY` with the location of your public key):
```bash
upsun ssh-key:add 'PATH_TO_YOUR_KEY'
```
You can also add it in the Console.
Now you are ready to use the key to [connect to an environment](./_index.md#2-connect-to-an-app-with-ssh).
### 3. Connect to your server with SSH keys
To connect to a server using SSH keys, find the details in the Console:
1. Open the [Upsun Console](https://console.platform.sh/).
1. Select a project.
1. In the **Environment** dropdown, select the environment you want to access.
1. Click the **SSH** dropdown.
1. Copy the ssh command for where you want access.
(Example: `ssh abcdefghi5k-main-7rqtwti--app@ssh.us-2.upsun.com`)
1. Enter the command into a terminal.
Note that if you have just added your SSH key,
you need to [redeploy your environment](./troubleshoot-ssh.md#redeploy-your-environment) before you can access it using SSH keys.
## Forwarding keys by default
It may be helpful to set your SSH client to always forward keys to Upsun servers, which can simplify other SSH or rsync commands.
To do so, include a block in your local `~/.ssh/config` file like so:
```text
Host *.us.upsun.com
ForwardAgent yes
Host *.eu.upsun.com
ForwardAgent yes
```
Include one `Host` entry for each Upsun region you want to connect to, such as `us-2` or `eu-4`.
(You can include other configuration as desired.)
# PHP [Authenticated Composer repositories](https://docs.upsun.com/languages/php/composer-auth.html)
Note
You can now use composable image (BETA) to install runtimes and tools in your application container. To find out more, see the dedicated documentation page.
[Packagist](https://packagist.org/) is the primary Composer repository for public PHP packages.
But you can also have Composer download PHP packages from a private, third-party Composer repository.
To make sure Composer has the necessary credentials to do so,
follow the instructions on this page.
## Before you begin
You need:
- A Upsun project using [PHP](../php/_index.md) and Composer
- Credentials to access a private third-party Composer repository
- The [Upsun CLI](../../administration/cli/_index.md)
## 1. Declare a private Composer repository
To allow Composer to download packages from a private third-party repository,
declare the repository in your Composer setup.
```json {location="composer.json"}
{
"repositories": [
{
"type": "composer",
"url": "https://PRIVATE_REPOSITORY_URL"
}
]
}
```
## 2. Set up Composer authentication using a variable
To allow Composer to successfully authenticate when accessing the declared private repository,
set an [`env:COMPOSER_AUTH` variable](../../development/variables/_index.md) for your project.
To do so, run the following command:
```bash
upsun variable:create --level project --name env:COMPOSER_AUTH \
--json true --visible-runtime false --sensitive true --visible-build true \
--value '{"http-basic": {"PRIVATE_REPOSITORY_URL": {"username": "USERNAME", "password": "PASSWORD"}}}'
```
The [`env:` prefix](../../development/variables/_index.md#top-level-environment-variables) means that the variable is exposed
as its own Unix environment variable.
The `--visible-runtime false` and `--visible-build true` flags mean the variable is available to Composer only during the build.
## 3. Clear your project's build cache
For security reasons, make sure that the authentication credentials aren't cached in your project's build container.
To do so, run the following command:
```bash
upsun project:clear-build-cache
```
## Access dependencies downloaded from a private repository
When you download a dependency from a private third-party Composer repository,
that dependency is usually hosted in a [private Git repository](../../development/private-repository.md).
Access to private Git repositories is restricted through the use of SSH keys.
But most private Composer tools mirror tagged releases of dependencies
and serve them directly without hitting the Git repository.
To avoid having to authenticate against a remote Git repository,
make sure your dependencies specify tagged releases.
# Languages [C#/.NET Core](https://docs.upsun.com/languages/dotnet.html)
Note
You can now use composable image (BETA) to install runtimes and tools in your application container. To find out more, see the dedicated documentation page.
Upsun supports deploying .NET applications by allowing developers to define a build process and pass its variables to the .NET Core build environment.
## Supported versions
You can select the major and minor version.
Patch versions are applied periodically for bug fixes and the like.
When you deploy your app, you always get the latest available patches.
7.0
6.0
8.0
### Specify the language
To use .Net Core, specify `dotnet` as your [app's `type`](/create-apps/app-reference/single-runtime-image.html#types):
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
:
type: 'dotnet:'
```
For example:
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
myapp:
type: 'dotnet:8.0'
```
## Building the application
To build basic applications in .NET containers, it's enough to use the [`dotnet publish` command](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish)
with the default [framework-dependent deployment](https://docs.microsoft.com/en-us/dotnet/core/deploying/#publish-framework-dependent):
```yaml {configFile="app"}
applications:
myapp:
type: 'dotnet:8.0'
hooks:
build: |
set -xe
dotnet publish --output "$PLATFORM_OUTPUT_DIR" \
-p:UseRazorBuildServer=false \
-p:UseSharedCompilation=false
```
where `PLATFORM_OUTPUT_DIR` is the output directory for compiled languages available at build time.
Typically, .NET Core builds start a collection of build servers, which are helpful for repeated builds.
On Upsun, however, if this process isn't disabled,
the build process doesn't finish until the idle timeout is reached.
As a result, you should include `-p` toggles that disable the Razor compiler for dynamic CSHTML pages (`UseRazorBuildServer`)
and the .NET MSBuild compiler (`UseSharedCompilation`).
If you want multiple builds for your application,
make sure to call `dotnet build-server shutdown` at the end of your build hook.
## Running the application
.NET Core applications should be started using the `web.commands.start` directive in `.upsun/config.yaml`.
This ensures that the command starts at the right moment and stops gracefully when a redeployment needs to be executed.
Also, should the program terminate for any reason, it's automatically restarted.
Note that the start command _must_ run in the foreground.
Incoming requests are passed to the application using either a TCP (default) or Unix socket.
The application must use the [appropriate environment variable](/create-apps/app-reference/single-runtime-image.md#where-to-listen) to determine the URI to listen on.
For a TCP socket ([recommended](https://go.microsoft.com/fwlink/?linkid=874850)), the application must listen on `http://127.0.0.1`,
using the `PORT` environment variable.
There is an Nginx server sitting in front of your application.
Serving static content via Nginx is recommended, as this allows you to control headers (including cache headers)
and also has marginal performance benefits.
Note that HTTPS is also terminated at the Nginx proxy,
so the `app.UseHttpsRedirection();` line in `Startup.cs` should be removed.
To force HTTPS-only, refer to the [routes documentation](../define-routes/https.md#enable-https).
The following example configures an environment to serve the static content folders commonly found in [ASP.NET MVC](https://dotnet.microsoft.com/apps/aspnet/mvc) templates using Nginx,
while routing other traffic to the .NET application.
```yaml {configFile="app"}
applications:
myapp:
type: 'dotnet:8.0'
web:
locations:
"/":
root: "wwwroot"
allow: true
passthru: true
rules:
# Serve these common asset types with customs cache headers.
\.(jpe?g|png|gif|svgz?|css|js|map|ico|bmp|eot|woff2?|otf|ttf)$:
allow: true
expires: 300s
commands:
start: "dotnet WebApplication1.dll"
```
You can also route all requests to the application unconditionally:
```yaml {configFile="app"}
applications:
myapp:
type: 'dotnet:8.0'
web:
locations:
"/":
allow: false
passthru: true
commands:
start: "dotnet WebApplication1.dll"
```
# Manage Upsun environments [Cancel an activity](https://docs.upsun.com/environments/cancel-activity.html)
If you have a stuck activity or you pushed a change you know doesn't work,
you can cancel a running or pending activity on an environment.
This works for activities such as builds, cron jobs, and source operations.
You can cancel activities using the [CLI](../administration/cli/_index.md)
or in the [Console](../administration/web/_index.md).
Open the environment where you want to cancel an activity.
In the activity log,
click More next to the activity you want to cancel.
Click Cancel.
## Non-cancellable activities
An activity can finish in between when you load the Console and when you click **Cancel**.
For example, when the activity is a [source operation](../create-apps/source-operations.md)
and the related build hook has already completed.
In such cases, you get a message that the activity can't be cancelled.
# Manage projects [Change a project's region](https://docs.upsun.com/projects/region-migration.html)
To host your project data, Upsun offers several [regions](../development/regions.md).
You specify a region when you create a project.
You can also change the project's region after it's created.
## Why migrate between regions
- Different data centers are located in different geographic areas.
You may want your site close to your users for improved performance.
- You may want to move to a region with a lower [environmental impact](../development/regions.md#environmental-impact).
## 1. Plan the migration
Before starting the migration process, you need to plan for it:
- Plan a time frame in which to handle the migration.
Your code shouldn't change during this time to ensure all changes are copied to the new project.
Prepare for a brief site outage when you migrate, just as with a relaunch of a site.
- Set your DNS Time-to-Live as low as possible.
This ensures the switch to the new site propagates as quickly as possible.
## 2. Create a new project
In the target region, [create a new project from scratch](
https://console.upsun.com/org/create-project/info?_utm_campaign=cta_deploy_marketplace_template&utm_source=public_documentation&_utm_medium=organic
).
If you plan to test for long, start with the least amount of resources on the project and then upsize it before switching the DNS.
## 3. Add code and environments
For a source integration with GitHub, BitBucket, or GitLab,
add the integration to your new project.
Your new project then mirrors the configured repository automatically.
## 4. Copy files
If you have files in a mount, first download them:
```bash
upsun mount:download
```
Then upload them to your new project:
```bash
upsun mount:upload
```
See more options on [how to export files](/learn/tutorials/exporting.md)
and [how to import files](/learn/tutorials/migrating/from-psh.md#6-import-data).
## 5. Copy data from services
For services with generated data such as Solr and Redis, you don't need to copy data directly.
Just rebuild the data in the new project.
To download data from persistent services such as databases,
see how to export and then import data for each service:
- [InfluxDB](../add-services/influxdb.md#export-data)
- [MongoDB](../add-services/mongodb.md#exporting-data)
- [MariaDB/MySQL](../add-services/mysql/_index.md#exporting-data)
- [PostgreSQL](../add-services/postgresql.md#exporting-data)
## 6. Migrate variables and project settings
Make sure anything else connected to your old project is moved to your new project:
- If you have project or environment variables defined on your old project, add them to your new project.
Get a list of all variables set outside of code by running `upsun variables`.
- Add any users to your new project that you want to continue to have access.
- Add any existing [integrations](../integrations/_index.md).
## 7. Test the site
Verify that the new site is working as desired before continuing.
You can leave the two projects running for as long as you need.
After you have finished all your testing, sync all your data (code, files, database) for the last time.
## 8. Switch to the new site
Now that you know the new project works, switch public traffic to that site:
1. Make sure your new project has the right plan size.
2. If possible, put your site into read-only mode or maintenance mode.
3. Add your domain names to your new project and remove them from the old project.
4. (Optional) Add any custom SSL certificates you have.
5. Update your DNS provider's records to point to the new site. See more on [setting custom domains](../domains/steps/_index.md).
It may take some time for the DNS change and SSL change to propagate.
Until it does, some browsers may not see the new site or may get an SSL mismatch error.
In most cases that resolves itself in 1--3 hours.
## 9. Remove the old project
Once the new project is running and the DNS has fully propagated, delete the old project.
## Alternative process
Although not directly supported by Upsun,
an agency named [Contextual Code](https://www.contextualcode.com/) has built a bash migration script.
This script automates most common configurations.
If your site is a typical single app with a single SQL database,
the script should take care of most of the process for you.
See more at the [Upsun Project Migration repository](https://gitlab.com/contextualcode/platformsh-migration).
# Manage Upsun environments [Change an environment's parent](https://docs.upsun.com/environments/change-parent.html)
All environments default to having another environment as their parent.
If you [branched](/glossary.md#branch) the environment from another,
its parent starts as the environment it was created from.
If you pushed a branch through Git or a [source integration](../integrations/source/_index.md),
the parent defaults to the default environment.
To change the environment's parent, follow these steps:
So if you have the environment new-feature and want to change its parent to main, run the following:
upsun environment:info -e new-feature parent main
If you're not using a [source integration](/integrations/source/_index.md),
you can also set a parent for your environment when pushing changes to it.
To do so, run the following command:
```bash
git push -o "environment.parent=PARENT_ENVIRONMENT_NAME"
```
Learn more about how to [trigger actions on `push`](/environments/_index.md#push-options).
# Use build and deploy hooks [Change hooks in different environments](https://docs.upsun.com/create-apps/hooks/vary-hooks-by-environment.html)
You might have certain commands you want to run only in certain environments.
For example enabling detailed logging in preview environments
or purging your CDN cache for production environments.
The `deploy` and `post_deploy` hooks can access all [runtime environment variables](../../development/variables/use-variables.md#use-provided-variables).
Use this to vary those hooks based on the environment.
Check the `PLATFORM_ENVIRONMENT_TYPE` variable to see if it's in a production environment:
```yaml {configFile="app"}
applications:
myapp:
hooks:
deploy: |
if [ "$PLATFORM_ENVIRONMENT_TYPE" = production ]; then
# Run commands only when deploying to production
else
# Run commands only when deploying to development or staging environments
fi
# Commands to run regardless of the environment
```
# Manage projects [Change the project timezone](https://docs.upsun.com/projects/change-project-timezone.html)
The project timezone affects [automated backups](../environments/backup.md).
The project timezone doesn't affect:
- [App runtime](/create-apps/timezone.md).
- [Cron jobs](/create-apps/app-reference/single-runtime-image.md#crons).
- [System logs](/increase-observability/logs/_index.md). UTC is the default timezone for all logs.
To change the timezone for a project, follow these steps:
1. Open the project where you want to change the timezone.
2. Click **Settings**.
3. Select the timezone from the list.
4. Click **Save**.
# Use build and deploy hooks [Comparison of hooks](https://docs.upsun.com/create-apps/hooks/hooks-comparison.html)
The following table presents the main differences among the three available hooks:
| Hook name | Failures stop build | Variables available | Services available | Timeout | Run on `worker` instances | Writable directories | Blocks requests | Runs on all redeploys\* |
| ------------- | ------------------- |-------------------- | ------------------ | ------- | ------------------------- | -------------------- | --------------- | --------------- |
| `build` | Yes | Build variables | No | 1 hour | Yes | `$PLATFORM_APP_DIR`, `$PLATFORM_CACHE_DIR`, and `/tmp` | No | No |
| `deploy` | No | Runtime variables | Yes | None | No | [Mounts](/create-apps/app-reference/single-runtime-image.md#mounts) | Yes | No |
| `post_deploy` | No | Runtime variables | Yes | None | No | [Mounts](/create-apps/app-reference/single-runtime-image.md#mounts) | No | Yes |
\* All of the hooks run with changes to the code or environment.
This column indicates which hooks run on a redeploy without any code changes.
## Build hook
The `build` hook is run after any [build flavor](/create-apps/app-reference/single-runtime-image.md#build).
During this hook, no services (such as a database) or any persistent file mounts are available
as the application hasn't yet been deployed.
The `build` hook can only use [environment variables](../../development/variables/use-variables.md#use-provided-variables)
that are available at build time.
During the `build` hook, there are three writeable directories:
- `$PLATFORM_APP_DIR`:
This is where your code is checked out and is the working directory when the `build` hook starts.
The contents of this directory after the build hook is the application that gets deployed.
- `$PLATFORM_CACHE_DIR`:
This directory persists between builds, but isn't deployed as part of your application.
It's a good place for temporary build artifacts that can be reused between builds.
It's shared by all builds on all branches.
- `/tmp`:
The temp directory is also useful for writing files that aren't needed in the final application,
but it's wiped between each build.
Note that `$PLATFORM_CACHE_DIR` is mapped to `/tmp`
and together they offer about 8GB of free space.
The only constraint on what can be downloaded during a `build` hook is the disk space available for builds.
This is _not_ the disk specified by your [resources configuration](/manage-resources.md).
If you exceed this limit, you receive a `No space left on device` error.
See how to [troubleshoot this error](../troubleshoot-disks.md#no-space-left-on-device).
The `build` hook runs only when the app or its runtime (variables and such) have changed.
Redeploys with no changes trigger only the `post_deploy` hook.
If you need the `build` hook to run, [manually trigger a build](../../development/troubleshoot.md#manually-trigger-builds).
Each hook is executed as a single script, so they're considered to have failed only if the final command in them fails.
To cause them to fail on the first failed command, add `set -e` to the beginning of the hook.
If a `build` hook fails for any reason, the build is aborted and the deploy doesn't happen.
Note that this only works for `build` hooks.
If other hooks fail, the deploy still happens.
### Timeout
Build hooks automatically time out if they run for 1 hour.
So if you accidentally add an unbroken loop, it gets cut off and you can continue with other activities.
## Deploy hook
The `deploy` hook is run after the app container has been started but before it has started accepting requests.
Note that the deploy hook only runs on [`web` instances](/create-apps/app-reference/single-runtime-image.md#web),
not [`worker` instances](/create-apps/app-reference/single-runtime-image.md#workers).
You can access other services at this stage (such as MySQL, Solr, Redis).
The disk where the application lives is read-only at this point.
This hook should be used when something needs to run once when new code is deployed.
It isn't run when a host is restarted (such as during region maintenance),
so anything that needs to run each time an instance of an app starts (regardless of whether there's new code)
should go in the `pre_start` key in [your `web` configuration](/create-apps/app-reference/single-runtime-image.md#web-commands).
For example, clearing the cache.
Be aware: The deploy hook blocks the site accepting new requests.
If your `deploy` hook is only a few seconds,
incoming requests in that time are paused and continue when the hook is finished.
So it effectively appears as if the site just took a few extra seconds to respond.
If the hook takes too long, requests can't be held and appear as dropped connections.
Only run tasks in your deploy hook that have to be run exclusively,
such as database schema updates or some types of cache clear (those where the code must match what's on the disk).
A task that can safely run concurrently with new incoming requests should be run as a `post_deploy` hook instead.
After a Git push, in addition to the log shown in the activity log,
the execution of the `deploy` hook is logged in the [deploy log](../../increase-observability/logs/access-logs.md#container-logs).
For example:
```bash
[2022-03-01 08:27:25.495579] Launching command 'bash export-config.sh'.
🔥 Successfully cleared configuration
🚀 Added new configuration details
```
Your `deploy` hook is tied to commits in the same way as your builds.
Once a commit has been pushed and a new build image has been created,
the result of both the `build` and `deploy` hooks are reused until there is a new git commit.
Redeploys with no changes trigger only the `post_deploy` hook.
If you need the `deploy` hook to run, [manually trigger a build](../../development/troubleshoot.md#manually-trigger-builds).
## Post-deploy hook
The `post_deploy` hook functions exactly the same as the `deploy` hook,
but after the container is accepting connections.
It runs concurrently with normal incoming traffic.
That makes it well suited to any updates that don't require exclusive database access.
What's "safe" to run in a `post_deploy` hook vs. in a `deploy` hook varies by the application.
Often times content imports, some types of cache warmups, and other such tasks are good candidates for a `post_deploy` hook.
In addition to the activity log, the `post_deploy` hook logs to the [post-deploy log](../../increase-observability/logs/access-logs.md#container-logs).
The `post_deploy` hook is the only hook that runs during a redeploy.
# Manage Upsun environments [Configure HTTP access control](https://docs.upsun.com/environments/http-access-control.html)
When developing your site, you might want to hide your preview environments from outside viewers.
Or you may find you have performance issues from [excessive bot access](https://community.platform.sh/t/diagnosing-and-resolving-issues-with-excessive-bot-access/792).
You can control access with a username and password **or** by allowing/denying specific IP addresses or networks.
This setting applies to the entire environment.
The settings for a specific environment are inherited by all of its children.
So if you have a `staging` environment and you [branch environments from it](/glossary.md#branch),
all of the environments branched from it inherit the same authentication information.
Changing access control triggers a new deploy of the current environment.
The changes don't propagate to child environments until they're [redeployed manually](../development/troubleshoot.md#force-a-redeploy).
## Use a username and password
You can set up one or more combinations of a username and password.
To add a username and password, follow these steps:
For example, to add the username name with the password 12321 to the test environment, run:
upsun environment:http-access -e test --auth name:12321
## Filter IP addresses
Alternatively, you can control access to environments by allowing or denying specific IP addresses or ranges of IP addresses.
The addresses should be in the [CIDR format](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing).
Both`4.5.6.7` and `4.5.6.0/8` are accepted formats.
Note that `allow` entries should come before `deny` entries in case they both match.
For example, the following configuration allows only the IP `198.51.100.0` to access your website.
```txt
198.51.100.0 allow
0.0.0.0/0 deny
```
# Configure what's served [Create a basic PHP app with a front controller](https://docs.upsun.com/create-apps/web/php-basic.html)
To handle dynamic requests to your PHP app, you might want to use a [front controller](https://en.wikipedia.org/wiki/Front_controller).
The following example shows how for such an app you might start defining [your web server](/create-apps/app-reference/single-runtime-image.md#web).
## Define a document root
Start by defining your document root (where all your publicly visible pages are).
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
web:
locations:
'/':
root: 'public'
```
## Define a front controller
Define where all requests that don't match a file in the document root are sent.
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
web:
locations:
'/':
root: 'public'
passthru: '/index.php'
index:
- index.php
```
In this case, `/index.php` acts as a front controller and handles dynamic requests.
Because it handles dynamic requests, you want to ensure that scripts are enabled
and responses aren't cached.
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
web:
locations:
'/':
...
scripts: true
# No caching for static files.
# (Dynamic pages use whatever cache headers are generated by the program.)
expires: -1
```
## Define rules
You might want to define specific rules for the location.
For example, you might want to allow all kinds of files except mp4 files.
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
web:
locations:
'/':
...
# Allow all file types generally
allow: true
rules:
# Disallow .mp4 files specifically.
\.mp4$:
allow: false
```
## Set different rules for specific locations
You might want to set specific rules for specific locations.
For example, you might have files in your `/public/images` directory that are served at `/images`.
You could define a specific cache time for them and limit them to only static image files.
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
web:
locations:
'/':
...
# Set a 5 min expiration time for static files in this location.
# Missing files are sent to front controller
# through the '/' location above.
'/images':
expires: 300
passthru: true
# Do not execute PHP scripts from this location and do not
# deliver their source code (for enhanced security).
scripts: false
allow: false
rules:
# Only allow static image files in this location
'\.(jpe?g|png|gif|svgz?|ico|bmp)$':
allow: true
```
## Complete example
```yaml {configFile="app"}
applications:
myapp:
source:
root: "/"
web:
locations:
'/':
root: 'public'
passthru: '/index.php'
index:
- index.php
scripts: true
# No caching for static files.
# (Dynamic pages use whatever cache headers are generated by the program.)
expires: -1
# Allow all file types generally
allow: true
rules:
# Disallow .mp4 files specifically.
\.mp4$:
allow: false
# Set a 5 min expiration time for static files in this location.
# Missing files are sent to front controller
# through the '/' location above.
'/images':
expires: 300
passthru: true
# Do not execute PHP scripts from this location and do not
# deliver their source code (for enhanced security).
scripts: false
allow: false
rules:
# Only allow static image files in this location
'\.(jpe?g|png|gif|svgz?|ico|bmp)$':
allow: true
```
# Security and compliance [Data retention](https://docs.upsun.com/security/data-retention.html)
Upsun logs and stores various types of data as a normal part of its business. This information is only retained as needed to perform relevant business functions. Retention periods vary depending on the type of data stored. If a legal obligation, law enforcement request, or ongoing business need so requires, data may be retained after the original purpose for which it was collected ceases to exist.
## Account information
Information relating to customer accounts (login information, billing information, etc.) is retained for as long as the account is active with Upsun.
Customers may request that their account be deleted and all related data be purged by opening a [support ticket](/learn/overview/get-support).
## System logs
System level access and security logs are maintained by Upsun for diagnostic purposes.
These logs aren't customer-accessible.
These logs are retained for at least 6 months and at most 2 years depending upon legal and standards compliance required for each system.
## Application logs
Application logs on each customer environment are retained with the environment.
Individual log files are truncated at 100 MB, regardless of their age.
See how to [access logs](../increase-observability/logs/access-logs.md).
When an environment is deleted, its application logs are deleted as well.
## Backups
The backups retention depends on the [automated backup policy](../environments/backup.md#automated-backups).
## Tombstone backups
When a project is deleted, Upsun takes a final backup of active environments, as well as the Git repository holding user code.
This final backup is to allow Upsun to recover a recently deleted project in case of accident.
These "tombstone" backups are retained for between 7 days and 6 months depending upon legal and standards compliance required for each system.
## Analytics
Upsun uses Google Analytics on various web pages, and so Google Analytics stores collected data for a period of time.
We have configured our Google Analytics account to store data for 14 months from the time you last accessed our site, which is the minimum Google allows.
## Trials
User data - which includes pushed code and data contained within services - is retained for a shorter period during trials.
See [Trial details](/glossary#trial).# Manage Upsun environments [Deactivate an environment](https://docs.upsun.com/environments/deactivate-environment.html)
If you have environments you aren't using, you may want to deactivate them to save resources for what you need.
To deactivate an environment, you need to be an admin for the project or the given environment.
Note
Your default environment is protected.
It can’t be deactivated through the Console or the CLI.
To change which environment is the default, see how to rename the default branch.
Deactivating the project results in the following:
* The environment becomes [inactive](/glossary.md#inactive-environment).
Unless it's reactivated, it's no longer deployed and isn't accessible from the web or via SSH.
* All services running on this environment are deleted.
* All data specific to the environment is deleted.
If the environment is reactivated, it syncs data from its parent environment.
## Deactivate an environment
To deactivate an environment, follow these steps:
Select the project with an environment you want to deactivate.
From the Environment menu, select the environment.
Click Settings.
In the row with Status, click Edit .
Select the checkbox to show you understand the consequences.
Click Deactivate & Delete Data.
Confirm your choice.
Run the following command:
upsun environment:deactivate ENVIRONMENT_NAME
## Delete the branch
Inactive environments still have branches in Git.
To delete the branch entirely, run the following command:
```bash
git push origin --delete BRANCH_NAME
```
## Reactivate an environment
Reactivating an environment [syncs](/glossary.md#sync) data from its parent environment.
To reactivate an inactive environment, follow these steps:
Select the project with an environment you want to reactivate.
From the Environment menu, select the environment.
Click Settings.
In the row with Status, click Edit .
Click Activate.
Run the following command:
upsun environment:activate ENVIRONMENT_NAME
If you're not using a [source integration](/integrations/source/_index.md),
you can also activate an environment when pushing changes to it.
To do so, run the following command:
```bash
git push -o "environment.status=active"
```
Learn more about how to [trigger actions on `push`](/environments/_index.md#push-options).# Manage projects [Delete a project](https://docs.upsun.com/projects/delete-project.html)
To delete a project, you must be an organization owner or have the [manage plans permission](../administration/users.md#organization-permissions).
To delete a Upsun project, including all data, code, and active environments:
On the tile of the project you want to delete, click More.
Click Edit plan.
Click Delete project.
To confirm your choice, enter the project’s name.
Click Yes, Delete Project.
Run the following command:
upsun project:delete --project PROJECT_ID
Read the consequences to deletion and enter y.
Enter the project title to confirm.
You are billed only for the portion of a month when the project was active.
When you remove all your projects from your user account,
you stop being charged.# Languages [Elixir](https://docs.upsun.com/languages/elixir.html)
Note
You can now use composable image (BETA) to install runtimes and tools in your application container. To find out more, see the dedicated documentation page.
Upsun supports building and deploying applications written in Elixir. There is no default flavor for the build phase, but you can define it explicitly in your build hook. Upsun Elixir images support both committed dependencies and download-on-demand. The underlying Erlang version is 22.0.7.
## Supported versions
You can select the major and minor version.
Patch versions are applied periodically for bug fixes and the like.
When you deploy your app, you always get the latest available patches.
1.15
1.14
### Specify the language
To use Elixir, specify `elixir` as your [app's `type`](/create-apps/app-reference/single-runtime-image.html#types):
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
:
type: 'elixir:'
```
For example:
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
myapp:
type: 'elixir:1.15'
```
## Built-in variables
Upsun exposes relationships and other configuration as [environment variables](../development/variables/_index.md).
Most notably, it allows a program to determine at runtime what HTTP port it should listen on
and what the credentials are to access [other services](../add-services/_index.md).
To get the `PORT` environment variable (the port on which your web application is supposed to listen) you would:
```elixir
String.to_integer(System.get_env("PORT") || "8888")
```
Some of the environment variables are in JSON format and are base64 encoded. You would need to import a JSON parsing library such as [JSON](https://hexdocs.pm/json/readme.html) or [Poison](https://hexdocs.pm/poison/api-reference.html) to read those. (There is an example for doing this to decode the `PLATFORM_RELATIONSHIPS` environment variable in the section [below](#accessing-services-manually).)
Tip
Remember config/prod.exs is evaluated at build time and has no access to runtime configuration. Use config/releases.exs to configure your runtime environment.
## Building and running the application
If you are using Hex to manage your dependencies, you need to specify the `MIX_ENV` environment variable:
```yaml {configFile="app"}
applications:
myapp:
type: 'elixir:1.15'
variables:
env:
MIX_ENV: 'prod'
```
The `SECRET_KEY_BASE` variable is generated automatically based on the [`PLATFORM_PROJECT_ENTROPY` variable](../development/variables/use-variables.md#use-provided-variables).
You can change it.
Include in your build hook the steps to retrieve a local Hex and `rebar`, and then run `mix do deps.get, deps.compile, compile` on your application to build a binary.
```yaml {configFile="app"}
applications:
myapp:
type: 'elixir:1.15'
hooks:
build: |
mix local.hex --force
mix local.rebar --force
mix do deps.get --only prod, deps.compile, compile
```
Note
That build hook works for most cases and assumes that your mix.exs file is located at your app root.
Assuming `mix.exs` is present at your app root and your build hook matches the above,
you can then start it from the `web.commands.start` directive.
The following basic app configuration is sufficient to run most Elixir applications.
```yaml {configFile="app"}
applications:
myapp:
type: 'elixir:1.15'
variables:
env:
MIX_ENV: 'prod'
hooks:
build: |
mix local.hex --force
mix local.rebar --force
mix do deps.get --only prod, deps.compile, compile
web:
commands:
start: mix phx.server
locations:
/:
allow: false
passthru: true
```
Note that there is still an Nginx proxy server sitting in front of your application. If desired, certain paths may be served directly by Nginx without hitting your application (for static files, primarily) or you may route all requests to the Elixir application unconditionally, as in the example above.
## Dependencies
The recommended way to handle Elixir dependencies on Upsun is using Hex.
You can commit a `mix.exs` file in your repository and the system downloads the dependencies in your `deps` section using the build hook above.
```elixir
defp deps do
[
{:platformshconfig, "~> 0.1.0"}
]
end
```
## Accessing Services
You can access service credentials to connect to [managed services](/add-services/) from environment variables present in the application container.
Consult each of the individual service documentation to see how to retrieve and surface credentials into your application.
- [ClickHouse](/add-services/clickhouse.html#usage-example)
- [Elasticsearch](/add-services/elasticsearch.html#use-in-app)
- [Gotenberg](/add-services/gotenberg.html#usage-example)
- [Headless Chrome](/add-services/headless-chrome.html#use-in-app)
- [InfluxDB](/add-services/influxdb.html#use-in-app)
- [Kafka](/add-services/kafka.html#use-in-app)
- [MariaDB/MySQL](/add-services/mysql.html#use-in-app)
- [Memcached](/add-services/memcached.html#use-in-app)
- [MongoDB](/add-services/mongodb.html#use-in-app)
- [Network Storage](/add-services/network-storage.html#usage-example)
- [OpenSearch](/add-services/opensearch.html#use-in-app)
- [PostgreSQL](/add-services/postgresql.html#use-in-app)
- [RabbitMQ](/add-services/rabbitmq.html#use-in-app)
- [Redis](/add-services/redis.html#use-in-app)
- [Solr](/add-services/solr.html#use-in-app)
- [Varnish](/add-services/varnish.html#usage-example)
- [Vault KMS](/add-services/vault.html#use-vault-kms)
### Accessing Services Manually
The services configuration is available in the environment variable `PLATFORM_RELATIONSHIPS`.
Given a [relationship](/create-apps/app-reference/single-runtime-image#relationships) defined in `.upsun/config.yaml`:
```yaml {configFile="app"}
applications:
myapp:
type: 'elixir:1.15'
[...]
# Relationships enable an app container's access to a service.
# The example below shows simplified configuration leveraging a default service
# (identified from the relationship name) and a default endpoint.
# See the Application reference for all options for defining relationships and endpoints.
relationships:
postgresql:
```
Assuming you have in `mix.exs` the Poison library to parse JSON:
```elixir
defp deps do
[
{:poison, "~> 3.0"}
]
end
```
And assuming you use `ecto` you could put in `config/config.exs`:
```elixir
relationships = Poison.decode!(Base.decode64!(System.get_env("PLATFORM_RELATIONSHIPS")))
[postgresql_config | _tail] = relationships["postgresql"]
config :my_app, Repo,
database: postgresql_config["path"],
username: postgresql_config["username"],
password: postgresql_config["password"],
hostname: postgresql_config["host"]
```
and setup Ecto during the deploy hook:
```yaml {configFile="app"}
applications:
myapp:
hooks:
deploy: |
mix do ecto.setup
```
# Activity scripts [Example: Discord](https://docs.upsun.com/integrations/activity/discord.html)
The following example activity script posts a message to a Discord channel every time it's triggered.
To use it, follow these steps:
1. In your Discord administrative interface, [create a new Discord webhook](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks).
Give it a name and specify the channel where it should post messages.
Copy the URL for the webhook.
2. Replace `DISCORD_URL` in the following script with your webhook URL.
3. Paste the code into a `.js` file.
4. Add it as a new [script integration](./_index.md#installing).
Specify which events should trigger it using the `--events` flag.
Optionally specify environments with the `--environments` flag.
Now, any activities that meet the events/environment criteria you specified are reported to Discord.
Once you have it working, you're free to modify the code below as desired.
For more on the message format, see the [Discord webhook API reference](https://discord.com/developers/docs/resources/webhook#execute-webhook).
```javascript
/**
* Sends a message to Discord.
*
* To control what events trigger it, use the --events switch in
* the Upsun CLI.
*
* @param {string} title
* The title of the message block to send.
* @param {string} message
* The message body to send.
*/
function sendDiscordMessage(title, message) {
const url = DISCORD_URL;
const messageTitle =
title + (new Date().getDay() === 5) ? " (On a Friday! :calendar:)" : "";
const body = {
content: messageTitle,
embeds: [
{
description: message,
},
],
};
const resp = fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
if (!resp.ok) {
console.log("Sending Discord message failed: " + resp.body.text());
}
}
sendDiscordMessage(activity.text, activity.log);
```
Common properties you may want to send to Discord (in the last line of the script) include:
- `activity.text`: A brief, one-line statement of what happened.
- `activity.log`: The complete build and deploy log output, as it would be seen in the Console log screen.
For more properties, see the [activity reference](./reference.md).
# Activity scripts [Example: Slack](https://docs.upsun.com/integrations/activity/slack.html)
The following example activity script posts a message to a Slack channel every time it's triggered.
To use it, follow these steps:
1. In your Slack administrative interface, [create a new Slack webhook](https://api.slack.com/messaging/webhooks).
You get a URL starting with `https://hooks.slack.com/`.
2. Replace `SLACK_URL` in the following script with your webhook URL.
3. Paste the code into a `.js` file.
4. Add it as a new [script integration](./_index.md#installing).
Specify which events should trigger it using the `--events` flag.
Optionally specify environments with the `--environments` flag.
Now, any activities that meet the events/environment criteria you specified are reported to Slack.
Once you have it working, you're free to modify the code below as desired.
For formatting more complex messages, see the [Slack messaging documentation](https://api.slack.com/messaging/composing/layouts).
```javascript
/**
* Sends a color-coded formatted message to Slack.
*
* To control what events trigger it, use the --events switch in
* the Upsun CLI.
*
* @param {string} title
* The title of the message block to send.
* @param {string} message
* The message body to send.
*/
function sendSlackMessage(title, message) {
const url = SLACK_URL;
const messageTitle =
title + (new Date().getDay() === 5) ? " (On a Friday! :calendar:)" : "";
const color = activity.result === "success" ? "#66c000" : "#ff0000";
const body = {
attachments: [
{
title: messageTitle,
text: message,
color: color,
},
],
};
const resp = fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
});
if (!resp.ok) {
console.log("Sending slack message failed: " + resp.body.text());
}
}
sendSlackMessage(activity.text, activity.log);
```
Common properties you may want to send to Slack (in the last line of the script) include:
- `activity.text`: A brief, one-line statement of what happened.
- `activity.log`: The complete build and deploy log output, as it would be seen in the Console log screen.
For more properties, see the [activity reference](./reference.md).
# Tutorials [Exporting data](https://docs.upsun.com/learn/tutorials/exporting.html)
As a Upsun user, your code and data belong to you.
At any time, you can download your site's data for local development, to back up your data, or to change provider.
## Before you begin
You need:
- [Git](https://git-scm.com/downloads)
- A Upsun account
- Code in your project
- Optional: the [Upsun CLI](/administration/cli/_index.md)
## 1. Download your app's code
Your app's code is maintained through the Git version control system.
To download your entire app's code history:
## 2. Download your files
Some files might not be stored in Git,
such as data your app writes [in mounts](/create-apps/app-reference/single-runtime-image.md#mounts).
You can download your files [using the CLI](/development/file-transfer.md#transfer-files-using-the-cli) or [using SSH](/development/file-transfer.md#transfer-files-using-an-ssh-client).
## 3. Download data from services
The mechanism for downloading from each service (such as your database) varies.
For services designed to hold non-persistent data, such as [Redis](/add-services/redis.md) or [Solr](/add-services/solr.md),
it's generally not necessary to download data as it can be rebuilt from the primary data store.
For services designed to hold persistent data, see each service's page for instructions:
- [MySQL](/add-services/mysql/_index.md#exporting-data)
- [PostgreSQL](/add-services/postgresql.md#exporting-data)
- [MongoDB](/add-services/mongodb.md#exporting-data)
- [InfluxDB](/add-services/influxdb.md#export-data)
## 4. Get environment variables
Environment variables can contain critical information such as tokens or additional configuration options for your app.
Environment variables can have different prefixes:
- Variables beginning with `env:` are exposed [as Unix environment variables](/development/variables/_index.md#top-level-environment-variables).
- Variables beginning with `php:` are interpreted [as `php.ini` directives](/development/variables/_index.md#php-specific-variables).
All other variables are [part of `$PLATFORM_VARIABLES`](/development/variables/use-variables.md#use-provided-variables).
To back up your environment variables:
Click Variables and access your variable’s values and settings.
Store the data somewhere secure on your computer.
Note that in the Console, you can’t access the value of variables that have been marked as sensitive.
Use the CLI to retrieve these values.
## What's next
- Migrate data from elsewhere [into Upsun](/learn/tutorials/migrating/_index.md).
- Migrate to [another region](/projects/region-migration.md).
- To use data from an environment locally, export your data and set up your [local development environment](/development/local/_index.md).
# [Feedback on specific docs pages](https://docs.upsun.com/feedback/report.html)
# Migrate your site to Upsun [From Platform.sh](https://docs.upsun.com/learn/tutorials/migrating/from-psh.html)
If you already have an app running somewhere else, you want to migrate it to Upsun and deploy it.
To do so, follow these steps.
## Before you begin
You need:
- An app that works and is ready to be built
- Code in Git
- A Upsun account -- if you don't already have one, [register](https://upsun.com/register/).
- The [Upsun CLI](/administration/cli/_index.md) installed locally
## 1. Export from previous system
Start by exporting everything you might need from your current app.
This includes data in databases, files on a file system,
and for some apps, such as Drupal, configuration that you need to export from the system into files.
## 2. Create a project
If you do not already have an organization created to put the project, you’ll first be instructed to create one.
Once you have done so, select that organization from the dropdown, and select Create from scratch.
In the form, fill in details like the project name and region.
You’ll be able to define resources for the project after your first push.
## 3. Add configuration
The exact configuration you want depends on your app.
You likely want to configure three areas:
- [The app itself](/create-apps/_index.md) -- this is the only required configuration
- [Services](/add-services/_index.md)
- [Routes](/define-routes/_index.md)
When you've added your configuration, make sure to commit it to Git.
## 4. Optional: Define a resource initialization strategy
By default, when you first deploy your project,
Upsun allocates [default resources](/manage-resources/resource-init.md) to each of your containers.
If you don't want to use those default resources,
define your own [resource initialization strategy](/manage-resources/resource-init#specify-a-resource-initialization-strategy) before pushing your code.
Alternatively, you can [amend those default container resources](/manage-resources/adjust-resources.md) after your project is deployed.
## 5. Push your code
The way to push your code to Upsun depends on
whether you're hosting your code with a third-party service using a [source integration](/integrations/source/_index.md).
If you aren't, your repository is hosted in Upsun
and you can use the CLI or just Git itself.
Get your project ID by running the following command:
upsun projects
Add Upsun as a remote repository by running the following command:
upsun project:set-remote PROJECT_ID
Push to the Upsun repository by running the following command:
upsun push
When you try to push, any detected errors in your configuration are reported and block the push.
After any errors are fixed, a push creates a new environment.
Add Upsun as a remote repository by running the following command:
git remote add upsun REPOSITORY_LOCATION
Push to the Upsun repository by running the following command:
git push -u upsun DEFAULT_BRANCH_NAME
When you try to push, any detected errors in your configuration are reported and block the push.
After any errors are fixed, a push creates a new environment.
## 6. Import data
Once you have an environment, you can import the data you backed up at step 1.
The exact process may depend on the service you use.
For SQL databases, for example, you can use a version of this command:
```bash
upsun sql < BACKUP_FILE_NAME
```
For any potential more details, see the [specific service](/add-services/_index.md).
## 7. Import files
Your app may include content files, meaning files that aren't intended to be part of your codebase so aren't in Git.
You can upload such files to [mounts you created](/create-apps/app-reference/single-runtime-image.md#mounts).
Upload to each mount separately.
Suppose you have the following mounts defined:
```yaml {configFile="app"}
applications:
myapp:
mounts:
'web/uploads':
source: local
source_path: uploads
'private':
source: local
source_path: private
```
`instance` mounts on Upsun are the equivalent of `local` mounts on Platform.sh.
To ensure continuity when migrating from Platform.sh to Upsun,
the `local` mount type works as an alias for the `instance` mount type.
However, it is recommended to change the type of your `local` mounts to `instance` or another [supported mount type](/create-apps/app-reference/single-runtime-image.html#define-a-mount).
For example:
```yaml {configFile="app"}
applications:
myapp:
mounts:
'web/uploads':
source: instance
source_path: uploads
'private':
source: instance
source_path: private
```
Then, to upload your files, run a command similar to the following:
```bash
upsun mount:upload --mount web/uploads --source ./uploads
upsun mount:upload --mount private --source ./private
```
Alternatively, you can upload to your mounts using a different [SSH method](/development/file-transfer.md#transfer-files-using-an-ssh-client).
## Optional: Add variables
If your app requires environment variables to build properly, [add them to your environment](/development/variables/set-variables.md).
## What's next
Now that your app is ready to be deployed, you can do more:
- [Add a domain](/domains/steps/_index.md).
- Set up for [local development](/development/local/_index.md).
- Configure [health notifications](/integrations/notifications.md).
- For monitoring and profiling, [integrate Blackfire](/increase-observability/application-metrics/blackfire.md).
# Languages [Go](https://docs.upsun.com/languages/go.html)
Note
You can now use composable image (BETA) to install runtimes and tools in your application container. To find out more, see the dedicated documentation page.
Upsun supports building and deploying applications written in Go using Go modules. They’re compiled during the Build hook phase, and support both committed dependencies and download-on-demand.
## Supported versions
You can select the major and minor version.
Patch versions are applied periodically for bug fixes and the like.
When you deploy your app, you always get the latest available patches.
1.23
1.22
1.21
1.20
### Specify the language
To use Go, specify `golang` as your [app's `type`](/create-apps/app-reference/single-runtime-image.html#types):
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
:
type: 'golang:'
```
For example:
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
myapp:
type: 'golang:1.23'
```
### Deprecated versions
The following versions are [deprecated](/glossary.html#deprecated-versions).
They're available, but they aren't receiving security updates from upstream and aren't guaranteed to work.
They'll be removed in the future,
so migrate to one of the [supported versions](#supported-versions).
1.19
1.18
1.17
1.16
1.15
1.14
1.13
1.12
1.11
1.10
1.9
1.8
## Go modules
The recommended way to handle Go dependencies on Upsun is using Go module support in Go 1.11 and later. That allows the build process to use `go build` directly without any extra steps, and you can specify an output executable file of your choice. (See the examples below.)
## Building and running the application
Assuming your `go.mod` and `go.sum` files are present in your repository, your application can be built with the command `go build`, to produce a working executable. You can then start it from the `web.commands.start` directive. Note that the start command _must_ run in the foreground. If the program terminates for any reason it is automatically restarted.
The following basic `.upsun/config.yaml` file is sufficient to run most Go applications.
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
myapp:
type: 'golang:1.23'
hooks:
build: |
# Modify this line if you want to build differently or
# use an alternate name for your executable.
go build -o bin/app
web:
upstream:
socket_family: tcp
protocol: http
commands:
# If you change the build output in the build hook above, update this line as well.
start: ./bin/app
locations:
/:
# Route all requests to the Go app, unconditionally.
allow: false
passthru: true
```
Note that there is still an Nginx proxy server sitting in front of your application.
If desired, certain paths may be served directly by Nginx without hitting your application (for static files, primarily)
or you may route all requests to the Go application unconditionally, as in the example above.
## Accessing services
To access various [services](../add-services/_index.md) with Go, see the following examples. The individual service pages have more information on configuring each service.
You can access service credentials to connect to [managed services](/add-services/) from environment variables present in the application container.
Consult each of the individual service documentation to see how to retrieve and surface credentials into your application.
- [ClickHouse](/add-services/clickhouse.html#usage-example)
- [Elasticsearch](/add-services/elasticsearch.html#use-in-app)
- [Gotenberg](/add-services/gotenberg.html#usage-example)
- [Headless Chrome](/add-services/headless-chrome.html#use-in-app)
- [InfluxDB](/add-services/influxdb.html#use-in-app)
- [Kafka](/add-services/kafka.html#use-in-app)
- [MariaDB/MySQL](/add-services/mysql.html#use-in-app)
- [Memcached](/add-services/memcached.html#use-in-app)
- [MongoDB](/add-services/mongodb.html#use-in-app)
- [Network Storage](/add-services/network-storage.html#usage-example)
- [OpenSearch](/add-services/opensearch.html#use-in-app)
- [PostgreSQL](/add-services/postgresql.html#use-in-app)
- [RabbitMQ](/add-services/rabbitmq.html#use-in-app)
- [Redis](/add-services/redis.html#use-in-app)
- [Solr](/add-services/solr.html#use-in-app)
- [Varnish](/add-services/varnish.html#usage-example)
- [Vault KMS](/add-services/vault.html#use-vault-kms)
# Infrastructure metrics [HTTP metrics](https://docs.upsun.com/increase-observability/metrics/http-metrics.html)
The HTTP metrics dashboard provides Upsun users with network-related metrics.
Those insights are designed to help them better understand the state of their
applications.
Those metrics can be accessed by clicking the **HTTP metrics** tab on the
environment page within the console.
The HTTP metrics dashboard can help you:
- Verify if there were any recent spikes in error responses
- Check bandwidth consumption to determine if there were any service interruptions
- Identify specific URLs causing site-wide issues
- Prioritize performance optimization (see [application metrics](../application-metrics/_index.md))
## HTTP requests status graph
The **HTTP requests** graph provides an aggregated view of the health of HTTP
requests made to the application. It reflects the status responses
(e.g. 1XX, 2XX, 3XX, 4XX, 5XX) of HTTP requests across a defined time frame.
This graph helps identify surge of error responses or periods of elevated
request activity.
## Bandwidth usage graph
The **Bandwidth** graph displays the data transfer volume. It represents
incoming (data the app receives) and outgoing (data the app sends) bandwidth
usage over time.
This graph helps identify bandwidth bottlenecks, optimize resource allocation,
and track bandwidth usage.
## Top 10 most impactful URLs
The **Top 10 URL Impact** graph and list pinpoint high-traffic or resource-intensive
URLs for targeted optimization or investigation. It showcases the evolution over
time of the top-10 most impactful URLs during a given time frame.
This graph helps identify potential trouble spots, understand user behavior, and
prioritize areas for optimization.
# Source integrations [Integrate with Bitbucket](https://docs.upsun.com/integrations/source/bitbucket.html)
If you have code in a Bitbucket repository, you might want to connect it to a Upsun project.
This means you can keep your Bitbucket workflows
and treat the Bitbucket repository as the source of truth for your code.
Your Upsun project becomes a mirror of your Bitbucket repository.
This means you shouldn't push code directly to Upsun.
Any changes you push directly get overwritten by the integration when changes happen in the Bitbucket repository.
When you set up an integration with Bitbucket,
it automates the following processes for you:
- Creating a new environment when a branch is created or a pull request is opened.
- Rebuilding the environment when new code is pushed to Bitbucket.
- Deleting the environment when a pull request is merged.
You can set up an integration with either Bitbucket Cloud
or a self-hosted [Bitbucket Server](https://confluence.atlassian.com/bitbucketserver/).
## Before you begin
To manage source integrations, you need to be a [project admin](../../administration/users.md).
You also need a Bitbucket Cloud or Bitbucket Server repository with working code.
## Bitbucket Cloud
### 1. Create an OAuth consumer
To integrate your Upsun project with an existing Bitbucket Cloud repository,
[create an OAuth consumer](https://support.atlassian.com/bitbucket-cloud/docs/use-oauth-on-bitbucket-cloud/):

Note
Be sure to define the above as a private consumer by checking the This is a private consumer box.
The **Callback URL** isn't important in this case.
You can set it to `http://localhost`.
Copy the **Key** and **Secret** for your consumer.
### 2. Enable the Cloud integration
To enable the integration, use either the [CLI](/administration/cli.html) or the [Console](/administration/web.html).
In both the CLI and Console, you can choose from the following options:
| CLI flag | Default | Description |
| ---------------- | ------- | ------------------------------------------------------------------------- |
| `fetch-branches` | `true` | Whether to mirror and update branches on Upsun and create inactive environments from them. When enabled, merging on a Upsun isn't possible. That is, merging environments must be done on the source repository rather than on the Upsun project. See note below for details related to this flag and synchronizing code from a parent environment. |
| `prune-branches` | `true` | Whether to delete branches from Upsun that don’t exist in the Bitbucket repository. When enabled, branching (creating environments) must be done on the source repository rather than on the Upsun project. Branches created on Upsun that are not on the source repository will not persist and will be quickly pruned. Automatically disabled when fetching branches is disabled. |
| `build-pull-requests` | `true` | Whether to track all pull requests and create active environments from them, which builds the pull request. |
| `resync-pull-requests` | `false` | Whether to sync data from the parent environment on every push to a pull request. |
| `resources-init` | `false` | To [specify a resource initialization strategy](/manage-resources/resource-init.md#first-deployment) for new containers. Once set, the strategy applies to **all** the deployments you launch through your source integration. See more information on [available resource initialization strategies](/manage-resources/resource-init.md#specify-a-resource-initialization-strategy). |
Note
To keep your repository clean and avoid performance issues, make sure you enable both the fetch-branches and prune-branches options.
### 3. Validate the integration
Verify that your integration is functioning properly [using the CLI](../overview.md#validate-integrations):
```bash
upsun integration:validate
```
#### Add the webhook manually
If the integration was added with the correct permissions, the necessary webhook is added automatically.
If you see a message that the webhook wasn't added, add one manually.
To configure a webhook on a Bitbucket repository,
you need to have Admin [user permissions](https://support.atlassian.com/bitbucket-cloud/docs/manage-webhooks/).
1. Get the webhook URL by running this command: `upsun
integration:get --property hook_url`.
1. Copy the returned URL.
1. Follow the [Bitbucket instructions to create a webhook](https://support.atlassian.com/bitbucket-cloud/docs/manage-webhooks/#Create-webhooks)
using the URL you copied.
Make sure to update the triggers to include all pull request events except comments and approval.
You can now start pushing code, creating new branches,
and opening pull requests
directly in your Bitbucket repository.
Your Upsun environments are automatically created and updated.
## Bitbucket Server
### 1. Generate a token
To integrate your Upsun project with a repository on a Bitbucket Server instance,
you first need to create an access token associated with your account.
[Generate a token](https://confluence.atlassian.com/display/BitbucketServer/HTTP+access+tokens).
and give it at least read access to projects and admin access to repositories.
Copy the token.
### 2. Enable the Server integration
To enable the integration, use either the CLI or the Console.
In both the CLI and Console, you can choose from the following options:
CLI flag
Default
Description
fetch-branches
true
Whether to mirror and update branches on Upsun and create inactive environments from them.
prune-branches
true
Whether to delete branches from Upsun that don’t exist in the Bitbucket server repository. Automatically disabled when fetching branches is disabled.
build-pull-requests
true
Whether to track all pull requests and create active environments from them, which builds the pull request.
pull-requests-clone-parent-data
true
Whether to clone data from the parent environment when creating a pull request environment.
To keep your repository clean and avoid performance issues,
make sure you enable both the fetch-branches and prune-branches options.
### 3. Validate the integration
Verify that your integration is functioning properly [using the CLI](../overview.md#validate-integrations):
```bash
upsun integration:validate
```
#### Add the webhook manually
If the integration was added with the correct permissions, the necessary webhook is added automatically.
If you see a message that the webhook wasn't added, add one manually.
To configure a webhook on a Bitbucket repository,
you need to have Admin [user permissions](https://support.atlassian.com/bitbucket-cloud/docs/manage-webhooks/).
1. Get the webhook URL by running this command: `upsun
integration:get --property hook_url`.
1. Copy the returned URL.
1. Follow the [Bitbucket instructions to create a webhook](https://confluence.atlassian.com/bitbucketserver076/managing-webhooks-in-bitbucket-server-1026535073.html#ManagingwebhooksinBitbucketServer-creatingwebhooksCreatingwebhooks)
using the URL you copied.
Send all events except comments and approval.
You can now start pushing code, creating new branches,
and opening pull requests
directly in your Bitbucket repository.
Your Upsun environments are automatically created and updated.
## Environment parent and status
When a **branch** is created in Bitbucket,
an environment is created in Upsun with the default branch as its parent.
It starts as an [inactive environment](/glossary.html#inactive-environment) with no data or services.
When a **pull request** is opened in Bitbucket,
an environment is created in Upsun with the pull request's target branch as its parent.
It starts as an [active environment](/glossary.html#active-environment) with a copy of its parent's data.
## Source of truth
When you add an integration, your Bitbucket repository is considered to be the source of truth for the project.
Your Upsun project is only a mirror of that repository and you can only push commits to Bitbucket.
In the Console, open the project you want to clone.
Click Code.
Click Git.
Run the command you find using Git.
When you do this, you're cloning from your integrated Bitbucket repository,
if you have the appropriate access to do so.
### Sync, fetch, and prune
An integration from Bitbucket to Upsun establishes that:
- Bitbucket is the source of truth, where Git operations occur
- Upsun is a mirror of that repository - provisioning infrastructure according to configuration, and orchestrating environments according to the branch structure of the Bitbucket repository
Actions that take place on Upsun don't affect commits on Bitbucket.
Because of this, the Bitbucket integration enables both `fetch-branches` (track branches on Bitbucket) and `prune-branches` (delete branches that don't exist on Bitbucket) by default.
You can change these settings but it is recommend to keep them.
When enabled by default, you are limited by design as to what actions can be performed within the context of a Upsun project with a Bitbucket integration:
| Action | Observation | Recommendation |
| :---------------- | :---------------- | :------- |
| Branch from parent | Running [`environment:branch`](/administration/cli/reference#environmentbranch) with the CLI, or selecting **Branch** in Console produces a new child environment, but it's deleted shortly after automatically. | Contribute to the Bitbucket repository itself by creating a branch and pull request. When the PR has been opened, a new environment will be provisioned for it. |
| Merge in parent | Running [`environment:merge`](/administration/cli/reference#environmentmerge) with the CLI fails locally, and the **Merge** option in Console is not clickable. | Review and merge pull requests and/or branches on the Bitbucket repository. |
| Merge into child (sync code) | Running [`environment:synchronize`](/administration/cli/reference#environmentsynchronize) with the CLI fails locally, and the **Sync** option in Console won't allow me to include `code` in that sync. | Perform the merge locally from a matching branch on Bitbucket. For example, clone the most recent parent (`git pull origin parent-branch`), switch to the pull request branch (`git checkout ga-staging`), and then merge the parent into the current branch (`git merge main`). |
## Pull request URLs
When a pull request is deployed, the integration reports the primary URL for the deployed environment.
So you get a link to the deployed environment right in the pull request.
If you have multiple routes,
ensure the correct one is reported by [specifying the primary route](/define-routes.html#route-configuration-reference).
# Source integrations [Integrate with GitHub](https://docs.upsun.com/integrations/source/github.html)
If you have code in a GitHub repository, you might want to connect it to a Upsun project.
This means you can keep your GitHub workflows
and treat the GitHub repository as the source of truth for your code.
Your Upsun project becomes a mirror of your GitHub repository.
This means you shouldn't push code directly to Upsun.
Any changes you push directly get overwritten by the integration when changes happen in the GitHub repository.
When you set up an integration with GitHub,
it automates the following processes for you:
- Creating a new environment when a branch is created or a pull request is opened.
- Rebuilding the environment when new code is pushed to GitHub.
- Deleting the environment when a pull request is merged.
## Before you begin
To manage source integrations, you need to be a [project admin](../../administration/users.md).
You also need a GitHub repository with working code.
## 1. Generate a token
To integrate your Upsun project with an existing GitHub repository,
you need to [generate a new token](https://github.com/settings/tokens/new).
You can generate a classic personal access token,
or a [fine-grained personal access token](https://github.blog/changelog/2022-10-18-introducing-fine-grained-personal-access-tokens/)
for even greater control over the permissions you grant.
For the integration to work,
your GitHub user needs to have permission to push code to the repository.
When you set up or update an integration, it also needs permission to manage its webhooks.
This means your user needs to be a repository admin to create the integration.
You can remove this permission after setup.
Make sure you give your token a description.
If you're generating a classic personal access token,
ensure the token has the appropriate scopes based on what you want to do:
| Scope | Purpose |
| --------------------- | ---------------------------------------------------------------------- |
| `admin:repo_hook` | To create webhooks for events in repositories. Always needed. |
| `public_repo` | To integrate with public repositories. |
| `repo` | To integrate with your private repositories. |
| `repo` and `read:org` | To integrate with private repositories in organizations you belong to. |
If you're generating a fine-grained personal access token,
ensure the token has the right [repository permissions](https://docs.github.com/en/rest/overview/permissions-required-for-fine-grained-personal-access-tokens?apiVersion=2022-11-28)
for the integration to work:
| Permission | Access level |
| ------------------| ----------------|
| `Commit statuses` | Read and write |
| `Contents` | Read and write |
| `Metadata` | Read-only |
| `Pull request` | Read and write |
| `Webhooks` | Read and write |
After you've set the needed scopes or permissions,
generate and copy your token.
## 2. Enable the integration
To enable the integration, use either the [CLI](/administration/cli.html) or the [Console](/administration/web.html).
GITHUB_URL is the base URL for your GitHub server if you self-host.
If you use the public https://github.com, omit the --base-url flag when running the command.
For example, if your repository is located at https://github.com/platformsh/platformsh-docs,
the command is similar to the following:
Optional: If your GitHub project isn’t hosted at github.com, enter your GitHub custom domain.
Click Continue.
Choose the repository to use for the project.
Check that the other options match what you want.
Click Add integration.
In both the CLI and Console, you can choose from the following options:
| CLI flag | Default | Description |
| ---------------- | ------- | ------------------------------------------------------------------------- |
| `fetch-branches` | `true` | Whether to mirror and update branches on Upsun and create inactive environments from them. When enabled, merging on a Upsun isn't possible. That is, merging environments must be done on the source repository rather than on the Upsun project. See note below for details related to this flag and synchronizing code from a parent environment. |
| `prune-branches` | `true` | Whether to delete branches from Upsun that don’t exist in the GitHub repository. When enabled, branching (creating environments) must be done on the source repository rather than on the Upsun project. Branches created on Upsun that are not on the source repository will not persist and will be quickly pruned. Automatically disabled when fetching branches is disabled. |
| `build-pull-requests` | `true` | Whether to track all pull requests and create active environments from them, which builds the pull request. |
| `build-draft-pull-requests` | `true` | Whether to also track and build draft pull requests. Automatically disabled when pull requests aren’t built. |
| `pull-requests-clone-parent-data` | `true` | Whether to clone data from the parent environment when creating a pull request environment. |
| `build-pull-requests-post-merge`| `false` | Whether to build what would be the result of merging each pull request. Turning it on forces rebuilds any time something is merged to the target branch. |
| `resources-init` | `false` | To [specify a resource initialization strategy](/manage-resources/resource-init.md#first-deployment) for new containers. Once set, the strategy applies to **all** the deployments you launch through your source integration. See more information on [available resource initialization strategies](/manage-resources/resource-init.md#specify-a-resource-initialization-strategy). |
To [keep your repository clean](/learn/bestpractices/clean-repository) and avoid performance issues, make sure you enable both the `fetch-branches` and `prune-branches` options.
## 3. Validate the integration
Verify that your integration is functioning properly [using the CLI](../overview.md#validate-integrations):
```bash
upsun integration:validate
```
### Add the webhook manually
If the integration was added with the correct permissions, the necessary webhook is added automatically.
If you see a message that the webhook wasn't added, add one manually.
To configure a webhook on a GitHub repository,
you need to have Admin [user permissions](https://docs.github.com/en/organizations/managing-user-access-to-your-organizations-repositories/repository-roles-for-an-organization#permissions-for-each-role).
1. Get the webhook URL by running this command: `upsun
integration:get --property hook_url`.
1. Copy the returned URL.
1. In your GitHub repository, click **Settings** > **Webhooks** > **Add webhook**.
1. In the **Payload URL** field, paste the URL you copied.
1. For the content type, select **application/json**.
1. Select **Send me everything**.
1. Click **Add webhook**.
You can now start pushing code, creating new branches,
and opening pull requests
directly in your GitHub repository.
Your Upsun environments are automatically created and updated.
## Environment parent and status
When a **branch** is created in GitHub,
an environment is created in Upsun with the default branch as its parent.
It starts as an [inactive environment](/glossary.html#inactive-environment) with no data or services.
When a **pull request** is opened in GitHub,
an environment is created in Upsun with the pull request's target branch as its parent.
It starts as an [active environment](/glossary.html#active-environment) with a copy of its parent's data.
## Source of truth
When you add an integration, your GitHub repository is considered to be the source of truth for the project.
Your Upsun project is only a mirror of that repository and you can only push commits to GitHub.
In the Console, open the project you want to clone.
Click Code.
Click Git.
Run the command you find using Git.
When you do this, you're cloning from your integrated GitHub repository,
if you have the appropriate access to do so.
### Sync, fetch, and prune
An integration from GitHub to Upsun establishes that:
- GitHub is the source of truth, where Git operations occur
- Upsun is a mirror of that repository - provisioning infrastructure according to configuration, and orchestrating environments according to the branch structure of the GitHub repository
Actions that take place on Upsun don't affect commits on GitHub.
Because of this, the GitHub integration enables both `fetch-branches` (track branches on GitHub) and `prune-branches` (delete branches that don't exist on GitHub) by default.
You can change these settings but it is recommend to keep them.
When enabled by default, you are limited by design as to what actions can be performed within the context of a Upsun project with a GitHub integration:
| Action | Observation | Recommendation |
| :---------------- | :---------------- | :------- |
| Branch from parent | Running [`environment:branch`](/administration/cli/reference#environmentbranch) with the CLI, or selecting **Branch** in Console produces a new child environment, but it's deleted shortly after automatically. | Contribute to the GitHub repository itself by creating a branch and pull request. When the PR has been opened, a new environment will be provisioned for it. |
| Merge in parent | Running [`environment:merge`](/administration/cli/reference#environmentmerge) with the CLI fails locally, and the **Merge** option in Console is not clickable. | Review and merge pull requests and/or branches on the GitHub repository. |
| Merge into child (sync code) | Running [`environment:synchronize`](/administration/cli/reference#environmentsynchronize) with the CLI fails locally, and the **Sync** option in Console won't allow me to include `code` in that sync. | Perform the merge locally from a matching branch on GitHub. For example, clone the most recent parent (`git pull origin parent-branch`), switch to the pull request branch (`git checkout ga-staging`), and then merge the parent into the current branch (`git merge main`). |
## Pull request URLs
When a pull request is deployed, the integration reports the primary URL for the deployed environment.
So you get a link to the deployed environment right in the pull request.
If you have multiple routes,
ensure the correct one is reported by [specifying the primary route](/define-routes.html#route-configuration-reference).
# Source integrations [Integrate with GitLab](https://docs.upsun.com/integrations/source/gitlab.html)
If you have code in a GitLab repository, you might want to connect it to a Upsun project.
This means you can keep your GitLab workflows
and treat the GitLab repository as the source of truth for your code.
Your Upsun project becomes a mirror of your GitLab repository.
This means you shouldn't push code directly to Upsun.
Any changes you push directly get overwritten by the integration when changes happen in the GitLab repository.
When you set up an integration with GitLab,
it automates the following processes for you:
- Creating a new environment when a branch is created or a merge request is opened.
- Rebuilding the environment when new code is pushed to GitLab.
- Deleting the environment when a merge request is merged.
## Before you begin
To manage source integrations, you need to be a [project admin](../../administration/users.md).
You also need a GitLab repository with working code.
## 1. Generate a token
To integrate your Upsun project with an existing GitLab repository,
generate a [project access token](https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html#create-a-project-access-token).
Ensure the token has the following scopes:
- `api` to access your API
- `read_repository` to read the repository
For the integration to work, your GitLab user needs push access to the repository and to configure a webhook on a GitLab repository, you need to have Maintainer or Owner user permissions.
Copy the token.
Note
To create a project access token, you need to have a sufficient GitLab license tier.
If you don’t see Access Tokens under Settings, upgrade your GitLab tier.
Alternatively, you can create a personal access token,
but that’s attached to a specific user rather than the project as a whole
and grants more permissions.
## 2. Enable the integration
To enable the integration, use either the [CLI](/administration/cli.html) or the [Console](/administration/web.html).
GITLAB_URL is the base URL for your GitLab server if you self-host.
If you use the public https://gitlab.com, omit the --base-url flag when running the command.
For example, if your repository is located at https://gitlab.com/platformsh/platformsh-docs,
the command is similar to the following:
Optional: If your GitLab project isn’t hosted at gitlab.com, enter your GitLab custom domain.
Click Continue.
Choose the repository to use for the project.
Check that the other options match what you want.
Click Add integration.
In both the CLI and Console, you can choose from the following options:
| CLI flag | Default | Description |
| ---------------- | ------- | ------------------------------------------------------------------------- |
| `fetch-branches` | `true` | Whether to mirror and update branches on Upsun and create inactive environments from them. When enabled, merging on a Upsun isn't possible. That is, merging environments must be done on the source repository rather than on the Upsun project. See note below for details related to this flag and synchronizing code from a parent environment. |
| `prune-branches` | `true` | Whether to delete branches from Upsun that don’t exist in the GitLab repository. When enabled, branching (creating environments) must be done on the source repository rather than on the Upsun project. Branches created on Upsun that are not on the source repository will not persist and will be quickly pruned. Automatically disabled when fetching branches is disabled. |
| `build-merge-requests` | `true` | Whether to track all merge requests and create active environments from them, which builds the merge request. |
| `build-wip-merge-requests` | `true` | Whether to also track and build draft merge requests. Automatically disabled when merge requests aren’t built. |
| `merge-requests-clone-parent-data` | `true` | Whether to clone data from the parent environment when creating a merge request environment. |
| `resources-init` | `false` | To [specify a resource initialization strategy](/manage-resources/resource-init.md#first-deployment) for new containers. Once set, the strategy applies to **all** the deployments you launch through your source integration. See more information on [available resource initialization strategies](/manage-resources/resource-init.md#specify-a-resource-initialization-strategy).
To [keep your repository clean](/learn/bestpractices/clean-repository) and avoid performance issues, make sure you enable both the `fetch-branches` and `prune-branches` options.
## 3. Validate the integration
Verify that your integration is functioning properly [using the CLI](../overview.md#validate-integrations):
```bash
upsun integration:validate
```
### Add the webhook manually
If the integration was added with the correct permissions, the necessary webhook is added automatically.
If you see a message that the webhook wasn't added, add one manually.
To configure a webhook on a GitLab repository,
you need to have Maintainer or Owner [user permissions](https://docs.gitlab.com/ee/user/permissions.html).
1. Get the webhook URL by running this command: `upsun
integration:get --property hook_url`.
1. Copy the returned URL.
1. In your GitLab repository, click **Settings** > **Webhooks**.
1. In the **URL** field, paste the URL you copied.
1. Under **Trigger**, select **Push events** and **Merge request events**.
1. Click **Add webhook**.
You can now start pushing code, creating new branches,
and opening merge requests
directly in your GitLab repository.
Your Upsun environments are automatically created and updated.
## Environment parent and status
When a **branch** is created in GitLab,
an environment is created in Upsun with the default branch as its parent.
It starts as an [inactive environment](/glossary.html#inactive-environment) with no data or services.
When a **merge request** is opened in GitLab,
an environment is created in Upsun with the merge request's target branch as its parent.
It starts as an [active environment](/glossary.html#active-environment) with a copy of its parent's data.
## Source of truth
When you add an integration, your GitLab repository is considered to be the source of truth for the project.
Your Upsun project is only a mirror of that repository and you can only push commits to GitLab.
In the Console, open the project you want to clone.
Click Code.
Click Git.
Run the command you find using Git.
When you do this, you're cloning from your integrated GitLab repository,
if you have the appropriate access to do so.
### Sync, fetch, and prune
An integration from GitLab to Upsun establishes that:
- GitLab is the source of truth, where Git operations occur
- Upsun is a mirror of that repository - provisioning infrastructure according to configuration, and orchestrating environments according to the branch structure of the GitLab repository
Actions that take place on Upsun don't affect commits on GitLab.
Because of this, the GitLab integration enables both `fetch-branches` (track branches on GitLab) and `prune-branches` (delete branches that don't exist on GitLab) by default.
You can change these settings but it is recommend to keep them.
When enabled by default, you are limited by design as to what actions can be performed within the context of a Upsun project with a GitLab integration:
| Action | Observation | Recommendation |
| :---------------- | :---------------- | :------- |
| Branch from parent | Running [`environment:branch`](/administration/cli/reference#environmentbranch) with the CLI, or selecting **Branch** in Console produces a new child environment, but it's deleted shortly after automatically. | Contribute to the GitLab repository itself by creating a branch and pull request. When the PR has been opened, a new environment will be provisioned for it. |
| Merge in parent | Running [`environment:merge`](/administration/cli/reference#environmentmerge) with the CLI fails locally, and the **Merge** option in Console is not clickable. | Review and merge pull requests and/or branches on the GitLab repository. |
| Merge into child (sync code) | Running [`environment:synchronize`](/administration/cli/reference#environmentsynchronize) with the CLI fails locally, and the **Sync** option in Console won't allow me to include `code` in that sync. | Perform the merge locally from a matching branch on GitLab. For example, clone the most recent parent (`git pull origin parent-branch`), switch to the pull request branch (`git checkout ga-staging`), and then merge the parent into the current branch (`git merge main`). |
## Merge request URLs
When a merge request is deployed, the integration reports the primary URL for the deployed environment.
So you get a link to the deployed environment right in the merge request.
If you have multiple routes,
ensure the correct one is reported by [specifying the primary route](/define-routes.html#route-configuration-reference).
# Languages [Lisp](https://docs.upsun.com/languages/lisp.html)
Note
You can now use composable image (BETA) to install runtimes and tools in your application container. To find out more, see the dedicated documentation page.
Upsun supports building and deploying applications written in Lisp using Common Lisp (the SBCL version) with ASDF and Quick Lisp support. They’re compiled during the Build phase, and support both committed dependencies and download-on-demand.
## Supported versions
You can select the major and minor version.
Patch versions are applied periodically for bug fixes and the like.
When you deploy your app, you always get the latest available patches.
3.3
3.2
3.1
3.0
### Specify the language
To use Lisp, specify `lisp` as your [app's `type`](/create-apps/app-reference/single-runtime-image.html#types):
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
:
type: 'lisp:'
```
For example:
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
myapp:
type: 'lisp:2.1'
```
## Assumptions
Upsun is making assumptions about your application to provide a more streamlined experience. These assumptions are the following:
- Your `.asd` file is named like your system name. For example `example.asd` has `(defsystem example ...)`.
Upsun will then run `(asdf:make :example)` on your system to build a binary.
If you don't want these assumptions, you can disable this behavior by specifying in your `.upsun/config.yaml`:
```yaml {configFile="app"}
applications:
myapp:
type: 'lisp:2.1'
build:
flavor: none
```
## Dependencies
The recommended way to handle Lisp dependencies on Upsun is using ASDF. Commit a `.asd` file in your repository and the system will automatically download the dependencies using QuickLisp.
## QuickLisp options
If you wish to change the distributions that QuickLisp is using, you can specify those as follows, specifying a distribution name, its URL and, an optional version:
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
:
type: 'lisp:'
runtime:
quicklisp:
DISTRIBUTION_NAME:
url: "..."
version: "..."
```
For example:
```yaml {configFile="app"}
applications:
# The app's name, which must be unique within the project.
myapp:
type: 'lisp:2.1'
runtime:
quicklisp:
quicklisp:
url: 'http://beta.quicklisp.org/dist/quicklisp.txt'
version: '2019-07-11'
```
## Built-in variables
Upsun exposes relationships and other configuration as [environment variables](../development/variables/_index.md).
To get the `PORT` environment variable (the port on which your web application is supposed to listen):
```lisp
(parse-integer (uiop:getenv "PORT"))
```
## Building and running the application
Assuming `example.lisp` and `example.asd` are present in your repository, the app is automatically built on push.
You can then start it from the `web.commands.start` directive.
Note that the start command _must_ run in the foreground. Should the program terminate for any reason it's automatically restarted. In the example below the app sleeps for a very, very long time. You could also choose to join the thread of your web server, or use other methods to make sure the program doesn't terminate.
The following basic `.upsun/config.yaml` file is sufficient to run most Lisp applications.
```yaml {configFile="app"}
applications:
myapp:
type: 'lisp:2.1'
web:
commands:
start: ./example
locations:
/:
allow: false
passthru: true
```
Note that a proxy server is still in front of your app.
If desired, certain paths may be served directly by the router without hitting your app (for static files, primarily) or you may route all requests to the Lisp application unconditionally, as in the example above.
## Accessing Services
The services configuration is available in the environment variable `PLATFORM_RELATIONSHIPS`.
To parse them, add the dependencies to your `.asd` file:
```lisp
:depends-on (:jsown :babel :s-base64)
```
The following is an example of accessing a PostgreSQL instance:
```lisp
(defun relationships ()
(jsown:parse
(babel:octets-to-string
(with-input-from-string (in (uiop:getenv "PLATFORM_RELATIONSHIPS"))
(s-base64:decode-base64-bytes in)))))
```
Given a relationship defined in `.upsun/config.yaml`: